12 Reaktionen

Veraltete Joomla Versionen auf dem Server via Bash-/Shell-Script finden

Geschätzte Lesedauer:

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.

Dieser Artikel wurde von Marius Burkard verfasst.

Marius Burkard ist Diplom-Wirtschaftsinformatiker und arbeitet seit 2006 als selbstständiger Software-Entwickler und Linux-Server-Administrator mit der Firma pixcept KG. Er ist unter anderem mitverantwortlich für die Projekte Was-lese-ich.de und ISPProtect.

11 Kommentare - bis jetzt!

Eigenen Kommentar verfassen
  1. Tobi
    schrieb am :

    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

  2. Matthes
    schrieb am :

    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:

     

    ./joomfind.sh: line 36: bc: command not found
    ./joomfind.sh: line 40: bc: command not found
    ./joomfind.sh: line 44: bc: command not found
    ./joomfind.sh: line 48: bc: command not found
    ./joomfind.sh: line 52: bc: command not found
    ./joomfind.sh: line 56: bc: command not found
    ./joomfind.sh: line 60: bc: command not found
    [INFO] Version 1.5.26 in /var/www/web1/htdocssperre ist ok.
    ./joomfind.sh: line 36: bc: command not found
    ./joomfind.sh: line 40: bc: command not found
    ./joomfind.sh: line 44: bc: command not found
    ./joomfind.sh: line 48: bc: command not found
    ./joomfind.sh: line 52: bc: command not found
    ./joomfind.sh: line 56: bc: command not found
    ./joomfind.sh: line 60: bc: command not found
    [INFO] Version 1.5.26 in /var/www/web3/htdocs ist ok.
    ./joomfind.sh: line 36: bc: command not found
    ./joomfind.sh: line 40: bc: command not found
    ./joomfind.sh: line 44: bc: command not found
    ./joomfind.sh: line 48: bc: command not found
    ./joomfind.sh: line 52: bc: command not found
    ./joomfind.sh: line 56: bc: command not found
    ./joomfind.sh: line 60: bc: command not found
    [INFO] Version 2.5.11 in /var/www/web4/htdocs ist ok.
    ./joomfind.sh: line 36: bc: command not found
    ./joomfind.sh: line 40: bc: command not found
    ./joomfind.sh: line 44: bc: command not found
    ./joomfind.sh: line 48: bc: command not found
    ./joomfind.sh: line 52: bc: command not found
    ./joomfind.sh: line 56: bc: command not found
    ./joomfind.sh: line 60: bc: command not found
    [INFO] Version 1.7.1 in /var/www/web4/htdocs/jupgrade ist ok.

    Die einzelnen Parte hinter [INFO] stimmen, nur was hat es mit dem command not found auf sich?

     

    vG

    Matthes

  3. Matthes
    schrieb am :

    okay, das passende Paket hat gefehlt 🙁

  4. Manuel
    schrieb am :

    Vielen Dank für dieses sehr hilfreiche Script!

  5. schrieb am :

    Gerne 🙂

    Ich habe das Skript heute noch einmal aktualisiert, so dass im 3er Bereich nun 3.1 aktuell ist.

  6. schrieb am :

    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

     

  7. Matthes
    schrieb am :

    Hallo Sören,

     

    das Problem habe ich leider auch, hast Du da spontan eine Lösung?

     

    (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

     

    viele Grüße

    Matthes!

  8. Marius Burkard Verfasser des Artikels
    schrieb am :

    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

  9. schrieb am :

    Wirst Du denn noch was daran machen, oder ist das für Dich erledigt?

  10. Marius Burkard Verfasser des Artikels
    schrieb am :

    Nein, ich werde das Skript auf absehbare Zeit nicht weiter überarbeiten.

Und jetzt du! Deine Meinung?

Erforderliche Felder sind mit einem Asterisk (*) gekennzeichnet. Die E-Mail-Adresse wird nicht veröffentlicht.
  1. Nach Absenden des Kommentar-Formulars erfolgt eine Verarbeitung der von Ihnen eingegebenen personenbezogenen Daten durch den datenschutzrechtlich Verantwortlichen zum Zweck der Bearbeitung Ihrer Anfrage auf Grundlage Ihrer durch das Absenden des Formulars erteilten Einwilligung.
    Weitere Informationen