Neben dem Script, welches dann schlussendlich den Viagraspamcode ausgibt (siehe neulich), werden noch weitere Scripte in die PHP-Dateien injiziert, diese fungieren dann als Backdoor, um beliebigen (php) Code auszuführen.

Damit das klappt, muss der Code quasi "auf Zuruf" ausgeführt werden. Eine Version, die ich gefunden habe, arbeitet mit eval(); in Verbindung mit base64_decode();, eine andere in Verbindung mit gzinflate(); und noch eine mittels str_rot13();.

Die, die mir am meisten Kopfzerbrechen machte, arbeitet mit preg_replace();, in Verwendung mit dem (bösen!) "e"-Modifier  - d.h. das Ergebnis der Ersetzung wird direkt ausgeführt. Ersetze also irgendeinen String mit einem Funktionsaufruf und *bam* - Code wird ausgeführt.

Wird der Befall erstmal bekannt, wäre es recht einfach, mittels grep in den Dateien nach diesen Funktionsnamen zu suchen, deshalb versuchen die Angreifer, diese zu verschleiern, genauso wie die Befehlskette, die am Ende ausgeführt wird.

PHP spielt ihnen dabei in die Hände, denn für PHP ist z.b. print_r($arr); genau das Gleiche wie $f = "print_r"; $f($arr);.
Der Name einer Funktion kann also als String in eine Variable gespeichert werden, und schreibt man diese dann mit "()" dazu, funktionierts.

Einen String kann man auch konkatinieren, also geht auch das: $f = "pri" . "nt_" . "r"; $f($arr);.

Genau das machen die Schlaumeierangreifer und produzieren nun munter Variationen von zusammengesetzten Funktionsnamen-Strings in den befallenen Dateien.

Um diese zu finden, muss man schon ziemlich tief in die Regular Expression Kiste greifen. Ich bleibe jetzt mal bei meinem Beispiel mit der harmlosen "print_r()" Funktion, "in echt" muss man nach den anderen Funktionsnamen suchen.

Disclaimer: Ich bin mit Regular Expressions zwar nicht gerade auf Kriegsfuss, aber alles andere als sattelfest. Sollte im Folgenden also was total krude sein, dann möge man mir das verzeihen, ich bin halt nur ein Designer/Developer Hybrid und kann von allem etwas, aber nix richtig :-))

Wie erwischt man also alle möglichen Variationen von "print_r", die nach dem Muster $xvxvxvxvx="pr"."in"."t_"."r" oder "p"."rin"."t"."_r" oder oder gebildet werden? Meine Idee war, es auf die möglichen Buchstaben und Konkatinierungszeichen und Anführungszeichen zu beschränken. Aber der Reihe nach:

Ich suche also nach einer Zeichenkette, die mit einem "$" beginnt, von einem beliebig langen Zufallsstring gefolgt wird, der auf ein "=" triff und danach geht das Spiel mit dem zusammengesetzten String los, dessen Bestandteile von Anführungszeichen eingeschlossen sind und die mit einem Punkt "." getrennt sind. Was hinten rauskommt, ist bekannt: Der Name der Funktion. Da ich nicht weiss, welche Buchstaben der Funktion hintereinanderstehen und wann getrennt wird, ist es am einfachsten, per Gruppe auf die Buchstaben zu checken: "[print_]+" würde "print_r" genauso finden, wie "pr" oder "in" oder "t_r". Das Pluszeichen besagt, das ein oder mehrere der Zeichen zwischen den eckigen Klammern vorkommen dürfen. Das ist nötig, damit zb "rint_r" auch gefunden wird. Nachteil ist, dass "rrrrrrrrriiiii" auch gefunden würde. Regex ist kein Ponyhof.
Nimmt man den "Konkatinierungspunkt" und die Anführungszeichen (sowohl ' als auch ") dazu, kommt man dem Ziel aber schon recht nahe: "[print_\.'\"]\+".
Um die Treffer noch mehr einzuengen, kombiniere ich das mit dem $ des Variablennamens, alles Mögliche dahinter (hier gibt es noch Optimierungsbedarf, anscheinend funktioniert (.*?) - non-greedy - nicht), den möglichen Leerzeichen und dem Gleichheitszeichen: "\$.*=[[:space:]]\?[print_\. '\"]\+".

Kombiniert man das nun mit rekursiver Suche in grep, hat man schon ein ganz gutes Tool an der Hand, um die befallenen Dateien zu finden:

grep -rn --include="*.php" "\$.*=[[:space:]]\?[preglac_\. '\"]\+" .

Dummerweise wirft dieser Befehl aber jede Menge "false positives" aus, wahrscheinlich, weil mir ein Dan Grad in RegEx noch lange verwehrt sein wird, aber wenn man sich die Ergenisse in eine Datei leiten lässt, dann kann man diese recht schnell auf die Schadcodeabschnitte scannen. Falls also ein Regex-Grosswesir das hier liest und den Begriff noch etwa präzisieren möchte, immer her damit in die Kommentare, ich aktualisiere dann gerne hier. :-)

Noch ein Wort zum Schluss: Es ist ja ganz schön, wenn man Stellen aufspüren kann, an denen der Code lauert - richtige Sicherheit und ein 100% cleanes System gibt es aber nur, wenn man es neu aufbaut - sonst hat man immer das Risiko, dass man den Code irgendwo übersehen hat, weil er vielleicht doch noch mal ganz anders verschleiert wurde, und da es sich dabei um eine Backdoor handelt, genügt eine einzige erreichbare Datei und der Spuk kann von vorne beginnen.

Als Übung und zum Lernen ist diese Beschäftigung mit der gehackten Kiste aber echt interessant.

Unbedingt lesen: http://blog.namics.com/2012/01/a-study-in-viagra.html

Nachtrag

Weitere Suchmuster, die infizierte Dateien aufspüren konnten (teilweise sehr lose, man muss dann die Ergebnisse nach den Hackmustern scannen, deshalb habe ich sie noch durch less geleitet):

find . -name "*.php" -print | xargs grep "eval(base64_decode(" | less
find . -name "*.php" -print | xargs grep "gzinflate" | less
find . -name "*.php" -print | xargs grep "eval(" | less
find . -name "*.php" -print | xargs grep "\['php_code'\]" | less
find . -name "*.php" -print | xargs grep "\"\^\"" | less

Ebenfalls hilfreich, aber ziemlich aufwendig: Im Erweiterungsmanager sieht man, ob Dateien verändert wurden:

Es lohnt, sich so angemahnte Dateien genauer anzuschauen, auch wenn es meistens falscher Alarm in Hinblick auf den Schadcode ist.
Die Info findet man, wenn man die Extension im Manager anklickt und dann auf "Informationen" geht.