Veraltete Joomla Versionen auf dem Server via Bash-/Shell-Script finden
Heute möchte ich mich einem Thema widmen, das zu sehr großen Problemen (gehackte Accounts, Mailspam, usw.) führen kann: Veraltete Joomla-Installationen auf dem Server.
Natürlich gilt das auch für andere Software. Die hier genannte Methode wird auch für andere Software in ähnlicher Weise funktionieren. Da Joomla sehr weit verbreitet ist und gerade auf Shared-Hosting Systemen ein oft genutztes (wenn nicht sogar am häufigsten) CMS (Content Management System) ist, behandle ich an dieser Stelle jedoch nur Joomla.
Vorbereitungen
Die erste Frage ist, wo wir die Version von Joomla in den Dateien erkennen können.
Dies ist je nach Version unterschiedlich. Bislang habe ich drei Dateien gefunden, die je nach Version, die Angaben enthalten:
/libraries/joomla/version.php
/libraries/cms/version/version.php
/includes/version.php
Die wichtigen Einträge dieser Dateien sind die Versionsnummer und die Unterversionsnummer, die in folgenden Variablen stehen:
var $RELEASE = ‚1.0‘;
var $DEV_LEVEL = ’12‘;
Als nächstes suchen wir uns die derzeit aktuellen (oder zumindest aktuellsten verfügbaren) Versionen einer Gruppe heraus. Für meinen Fall habe ich das für Version 1.5 (1.5.26), Version 2.5 (2.5.9) und Version 3.0 (3.0.3) gemacht.
Joomla-Installationen finden
Ein markantes Kennzeichen von Joomla-Installationen ist unter anderem der „components“ Ordner, daher beginnen wir mit einer Suche nach allen Ordnern mit diesem Namen und klammern gleichzeitig alle Ordner im Unterverzeichnis „administrator“ aus. Der Basisordner /var/www muss natürlich je nach System angepasst werden.
[pastacode lang=“bash“ message=“Kommandozeile“ highlight=““ provider=“manual“]
find /var/www/ -type d -name 'components' | grep -v '/administrator/components'
[/pastacode]
Mit diesem Befehl bekommen wir eine Liste all dieser Ordner ausgegeben. Mit dem Befehl „dirname“ können wir den Pfad ermitteln, in dem sich der Ordner „components“ befindet, also den vermeintlichen Basis-Ordner der Joomla-Installation.
Dies machen wir in einer Schleife für alle gefundenen Ordner:
[pastacode lang=“bash“ message=“Kommandozeile“ highlight=““ provider=“manual“]
for L in `find /var/www/ -type d -name 'components' | grep -v '/administrator/components' ; do
D=`dirname $L` ;
done
[/pastacode]
Version und Unterversion ermitteln
Um die Version zu ermitteln bedienen wir uns einer Kombination aus den Befehlen „grep“ und „sed“.
Zuerst prüfen wir, an welchem der drei Orte die Versionsdatei vorhanden ist.
[pastacode lang=“bash“ message=“Kommandozeile“ highlight=““ provider=“manual“]
F=$D/libraries/joomla/version.php ;
F2=$D/libraries/cms/version/version.php ;
F3=$D/includes/version.php ;
if [[ -e "$F" || -e "$F2" || -e "$F3" ]] ; then
if [[ -e "$F" ]] ; then
F=$F ;
elif [[ -e "$F2" ]] ; then
F=$F2 ;
elif [[ -e "$F3" ]] ; then
F=$F3 ;
fi
else
echo "Keine Joomla Versionsdatei gefunden." ;
fi
[/pastacode]
Nun Lesen wir aus der gefundenen Datei die Version und Unterversion aus:
[pastacode lang=“bash“ message=“Kommandozeile“ highlight=““ provider=“manual“]
VERSION=`grep '$RELEASE' $F | sed -r "s/^.*=\s*'(.*)'.*$/\1/g"` ;
SUBVERSION=`grep '$DEV_LEVEL' $F | sed -r "s/^.*=\s*'(.*)'.*$/\1/g"` ;
[/pastacode]
Versionen vergleichen
Da die Versionsnummern keine Ganzzahlen sein müssen, können wir diese nicht einfach innerhalb des Bash Skriptes mit -lt etc. prüfen sondern müssen uns eines Umwegs über das Programm bc bedienen:
[pastacode lang=“bash“ message=“Kommandozeile“ highlight=““ provider=“manual“]
ISOK=1 ;
if [[ $(echo "if (${VERSION} < 1.5) 1 else 0" | bc) -eq 1 ]] ; then
# version ist kleiner als 1.5
ISOK=0 ;
elif [[ $(echo "if (${VERSION} == 1.5) 1 else 0" | bc) -eq 1 && $(echo "if (${SUBVERSION} < 26) 1 else 0" | bc) -eq 1 ]] ; then
# version ist 1.5.x aber kleiner als 1.5.26
ISOK=0 ;
### usw. weitere Versionprüfungen
else
ISOK=1 ;
fi
[/pastacode]
Das fertige Skript
Zum Schluss bauen wir alle genannten Skriptteile zusammen und fügen noch ein paar kleinere Annehmlichkeiten ein. Das Skript sucht nach allen Joomla-Installationen im angegebenen Verzeichnis und gibt dann eine Information darüber aus, ob die gefundenen Installationen aktuell sind. Natürlich kann man eigentlich eine 1.5.26 Installation nicht mehr als aktuell bezeichnen, da es jedoch die aktuellste 1.5.x Version ist und ein Update auf eine 2.5 oder 3.0 oftmals sehr problematisch ist, werden diese Versionen hier mit OK markiert.
Eine Beispielausgabe des Skriptes:
[pastacode lang=“bash“ message=“Ausgabe“ highlight=““ provider=“manual“]
[INFO] Version 1.5.26 in /var/www/xxx ist ok.
[WARN] Veraltete Joomla Version 1.0.12 in /var/www/yyy
[WARN] Veraltete Joomla Version 1.5.14 in /var/www/zzz
[WARN] Veraltete Joomla Version 2.5.8 in /var/www/aaa
[WARN] Veraltete Joomla Version 1.5.10 in /var/www/bbb
[/pastacode]
Und hier nun das komplette Skript. Einfach als „joomlascan.sh“ speichern und via
bash joomlascan.sh
ausführen. Wenn es mit bash joomlascan.sh liste.csv ausgeführt wird, erhält man in der Datei liste.csv eine Auflistung der als veraltet gefundenen Installationen:
[pastacode lang=“bash“ message=“Ausgabe“ highlight=““ provider=“manual“]
/var/www/yyy;1.0.12;1.5.26
/var/www/zzz;1.5.14;1.5.26
/var/www/aaa;2.5.8;2.5.9
/var/www/bbb;1.5.10;1.5.26
[/pastacode]
[pastacode lang=“bash“ message=“Shell-Script“ highlight=““ provider=“manual“]
#!/bin/bash
# aktuelle version 1.5.x
CUR15=26
# aktuelle version 2.5.x
CUR25=14
# aktuelle version 3.x
CUR3=5
# ausgabe als CSV in Datei (optionaler Parameter)
OUTFILE=$1
if [[ "$OUTFILE" != "" ]] ; then
# CSV Ausgabedatei leeren
echo -n "" > $OUTFILE ;
fi
for L in `find /var/www -type d -name 'components' | grep -v '/administrator/components' | grep -v '/tmp/'` ; do
D=`dirname $L` ;
F=$D/libraries/joomla/version.php ;
F2=$D/libraries/cms/version/version.php ;
F3=$D/includes/version.php ;
ISOK=0 ;
SHOWNEWEST="" ;
IMPORTANCE=0 ;
if [[ -e "$F" || -e "$F2" || -e "$F3" ]] ; then
if [[ -e "$F" ]] ; then
F=$F ;
elif [[ -e "$F2" ]] ; then
F=$F2 ;
elif [[ -e "$F3" ]] ; then
F=$F3 ;
fi
VERSION=`grep '$RELEASE' $F|sed -r "s/^.*=\s*'(.*)'.*$/\1/g"` ;
SUBVERSION=`grep '$DEV_LEVEL' $F|sed -r "s/^.*=\s*'(.*)'.*$/\1/g"` ;
if [[ $(echo "if (${VERSION} < 1.5) 1 else 0" | bc) -eq 1 ]] ; then
# version ist kleiner als 1.5
SHOWNEWEST="1.5.${CUR15}" ;
IMPORTANCE=3 ;
elif [[ $(echo "if (${VERSION} == 1.5) 1 else 0" | bc) -eq 1 && $(echo "if (${SUBVERSION} < ${CUR15}) 1 else 0" | bc) -eq 1 ]] ; then # version ist 1.5.x aber kleiner als aktuellste Version SHOWNEWEST="1.5.${CUR15}" ; IMPORTANCE=2 ; elif [[ $(echo "if (${VERSION} == 1.6) 1 else 0" | bc) -eq 1 ]] ; then # Version ist 1.6 SHOWNEWEST="2.5.${CUR25}" ; IMPORTANCE=2 ; elif [[ $(echo "if (${VERSION} == 1.7) 1 else 0" | bc) -eq 1 ]] ; then # Version ist 1.7 SHOWNEWEST="2.5.${CUR25}" ; IMPORTANCE=2 ; elif [[ $(echo "if (${VERSION} > 1.7) 1 else 0" | bc) -eq 1 && $(echo "if (${VERSION} < 2.5) 1 else 0" | bc) -eq 1 ]] ; then
# Version ist irgendwo zwischen 1.7 und 2.5
SHOWNEWEST="2.5.${CUR25}" ;
IMPORTANCE=2 ;
elif [[ $(echo "if (${VERSION} == 2.5) 1 else 0" | bc) -eq 1 && $(echo "if (${SUBVERSION} < ${CUR25}) 1 else 0" | bc) -eq 1 ]] ; then
# Version ist 2.5 aber kleiner als aktuellste Version
SHOWNEWEST="2.5.${CUR25}" ;
IMPORTANCE=1 ;
elif [[ $(echo "if (${VERSION} == 3) 1 else 0" | bc) -eq 1 ]] ; then
# Version ist 3.0 aber kleiner als aktuellste Version
SHOWNEWEST="3.1.${CUR3}" ;
IMPORTANCE=2 ;
elif [[ $(echo "if (${VERSION} == 3.1) 1 else 0" | bc) -eq 1 && $(echo "if (${SUBVERSION} < ${CUR3}) 1 else 0" | bc) -eq 1 ]] ; then # Version ist 3.1 aber kleiner als aktuellste Version SHOWNEWEST="3.1.${CUR3}" ; IMPORTANCE=1 ; else ISOK=1 ; echo "[INFO] Version $VERSION.$SUBVERSION in $D ist ok." ; fi else # Scheint keine Joomla Installation zu sein... ISOK=1 ; fi ; if [[ $ISOK -eq 0 ]] ; then echo "[WARN] Veraltete Joomla Version $VERSION.$SUBVERSION in $D" ; if [[ "$OUTFILE" != "" ]] ; then # CSV Datei schreiben echo "\"$D\";$VERSION.$SUBVERSION;$SHOWNEWEST;$IMPORTANCE" >> $OUTFILE ;
fi
fi
done
exit 0 ;
[/pastacode]
Einen „Fehler“ hat das Skript: Es kann Mambo Installationen nicht erkennen und gibt diese als „OK“ aus, egal welche Version enthalten ist. Dies könnte aber jeder für sich noch einbauen, sofern notwendig.
Vielen Dank für diesen Artikel! Ich suche und wenn ich nichts finde werde ich wohl selbst ein Tool bauen um die verschiedenen Versionen von Kunden CMS-Systemen zu überwachen um diese bei Überalterung informieren zu können. Da ist dein Script schonmal ein Anfang. Weiß zufällig noch jemand Seiten für andere CMS-Systeme?
Danke
Hallo,
vielen Dank für das coole Script, das macht mir das Leben doch manchmal etwas leicher, da ich verschiedene Joomla-Versionen im Einsatz habe.
Allerdings bin ich mit der Ausgabe nicht ganz zufrieden, die bei mir wie folgt aussieht:
Die einzelnen Parte hinter [INFO] stimmen, nur was hat es mit dem command not found auf sich?
vG
Matthes
okay, das passende Paket hat gefehlt 🙁
Vielen Dank für dieses sehr hilfreiche Script!
Gerne 🙂
Ich habe das Skript heute noch einmal aktualisiert, so dass im 3er Bereich nun 3.1 aktuell ist.
Hier gibt es nun auch das Skript für WordPress
https://www.soeren-hentzschel.at/technik/linux-server/2013/08/22/veraltete-wordpress-versionen-auf-dem-server-via-bash-shell-script-finden/
Könntest Du das Script noch mal auf Joomla 3.5 aktualisieren?
Seit dem Update bekomme ich folgende Fehlermeldungen:
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
Hallo Sören,
das Problem habe ich leider auch, hast Du da spontan eine Lösung?
viele Grüße
Matthes!
Hallo Matthes,
leider kann ich dir spontan nicht einmal die Ursache dieses Fehlers nennen. Mich wundert vor allem, dass er erst seit einem Update zu kommen scheint. Ich muss aber auch sagen, dass ich mich mit diesen Skripten nicht mehr auseinandergesetzt habe, da sie in ein kommerzielles Projekt (ISPProtect) eingeflossen sind und dort in PHP weiterentwickelt wurden/werden.
Viele Grüße
Marius
Wirst Du denn noch was daran machen, oder ist das für Dich erledigt?
Nein, ich werde das Skript auf absehbare Zeit nicht weiter überarbeiten.