Skip to content

Cross-Site Scripting im Überblick, Teil 3: Der MySpace-Wurm Samy

Eine persistente XSS-Schwachstelle in einer Webanwendung kann unter Umständen von einem Webwurm zur Verbreitung genutzt werden. Der infizierte dann nicht wie ein herkömmlicher Computerwurm zig verschiedene Server oder Benutzerrechner, sondern die Profile der Benutzer der betroffenen Webanwendung oder ähnliches. Er ist also auf den einen Server mit der betroffenen Webanwendung beschränkt, kann dort aber auch einigen Schaden anrichten.

Der erste, oder zumindest der erste allgemein bekannt gewordene, Web-Wurm war der MySpace-Wurm Samy, der sich am 4. Oktober 2005 auf MySpace ausbreitete.

So funktionierte der MySpace-Wurm

Samy Kamkar war der Meinung, zu wenig Freunde auf MySpace zu haben. Samy (der Wurm) sollte das ändern. Und tat das sehr erfolgreich. Ausgehend von Samy Kamkars Profilseite verbreitete sich der Wurm über eine persistente XSS-Schwachstelle in die Profilseiten der Besucher eines befallenen Profils. Über einen XMLHttpRequest wurde Samy zum Freund und 'Hero' des Besuchers gemacht und der Wurmcode in dessen Profilseite integriert. Innerhalb von 20 Stunden hatte Samy Kamkar mehr als 1 Million Freunde und Samy (der Wurm) entsprechend viele Profile verseucht. MySpace musste den Betrieb vorübergehend komplett einstellen, um den Wurm zu stoppen und alle befallenen Seiten zu reinigen.

Die folgende Beschreibung dey MySpace-Wurms basiert auf Samy Kamkars eigener Beschreibung. Die Methoden, um MySpaces Filter zu umgehen, sehen inzwischen recht altmodisch aus. Der Wurm ist ja auch schon fast 10 Jahre alt.

Bei der Entwicklung musste Samy Kamkar einige Schutzmaßnahmen von MySpace und weitere Einschränkungen überwinden. Was ihm erfolgreich gelang, wie der Erfolg des Wurms eindrucksvoll bewies.

Den Sourcecode des Wurm finden Sie sowohl in der Originalformatierung als auch in einer angepassten, lesbareren Formatierung sowie in einer kommentierten Version mit "sprechenden" Variablennamen hier. Die kommentierte Version sollte, vor allem in Verbindung mit den folgenden Erklärungen, selbsterklärend sein. In der Beschreibung ist das Wort "Code" teilweise mit den entsprechenden Quellen im Sourecode verlinkt.

  1. MySpace blockierte die meisten HTML-Tags, insbesondere <script>-Tags, HREF-Tags mit JavaScript etc.. Nicht gefiltert wurden jedoch CSS-Tags. Samy nutzte aus, das einige Browser wie zum Beispiel der Internet Explorer und einige Safari-Versionen JavaScript-Code in CSS-Tags auswerteten. Dadurch funktionierte der Wurm-Code nicht in jedem Browser, aber es blieben genug potentielle Opfer übrig.
    Code: <div style="background:url('javascript:alert(1)')">

  2. MySpace filterte die Zeichenkette "javascript" überall aus - nicht aber "java\nscript", was von einigen Browsern als "javascript" interpretiert wird (\n ist der Zeilenumbruch, Newline).
    Code: <div style="background:url('java
    script:alert(1)')">


  3. Innerhalb des <div>-Tags konnten keine Quote-Zeichen verwendet werden, da sowohl ' als auch " bereits verwendet wurden. Nun ist es ziemlich schwierig, JavaScript ohne Quote-Zeichen zu programmieren. Als Ausweg hat Samy Kamkar den JavaScript-Code in einem Ausdruck gespeichert und dann mit dessen Namen aufgerufen und ausgeführt. Dadurch konnte das einfache Quote-Zeichen (') verwendet werden.
    Code: <div id="mycode" expr="alert('Hallo!')" style="background:url('java
    script:eval(document.all.mycode.expr)')">

    Die relevanten Teile sind im unformatierten Sourcecode blau markiert.

  4. Außer einfacher Quote-Zeichen (') wurden auch doppelte Quote-Zeichen (") benötigt. Das escapen (zum Beispiel foo\"bar) funktionierte nicht, da MySpace alle maskierten Quote-Zeichen ausfilterte. Als Ausweg hat Samy Kamkar die doppelten Quote-Zeichen mit der Funktion String.fromCharCode() aus ihrem Dezimalcode erzeugt.
    Code: <div id="mycode" expr="alert('Doppeltes Quote-Zeichen: ' + String.fromCharCode(34))" style="background:url('java
    script:eval(document.all.mycode.expr)')">


  5. Um den Wurm-Code auf die Profilseite des Opfers zu kopieren musste auf den Quelltext der Seite zugegriffen werden, um daraus die ID des Benutzers zu lesen. Eigentlich ginge dies über document.body.innerHTML - wenn MySpace nicht die Zeichenkette "innerHTML" überall ausgefiltert hätte. Als Ausweg wurde "innerHTML" in einem eval()-Aufruf aus zwei Strings zusammengesetzt:
    Code: alert(eval('document.body.inne' + 'rHTML'));

  6. Bei der Suche nach der ID des Benutzers, "friendID" würde auch der eigene Code gefunden werden, da der diese Zeichenkette ja auch enthält. Daher muss das zu suchende Wort ebenfalls zusammengesetzt werden. Der gleiche Fall tritt auf, wenn der Wurm-Code für die Weiterverbreitung von der aktuellen Seite gelesen wird.
    Code: var index = html.indexOf('m' + 'ycode');

  7. Um die Profilseite des Opfers zu ändern, wurden XMLHttpRequests verwendet. Das ginge zwar auch ohne, zum Beispiel über versteckte iFrames, aber der im Hintergrund ablaufende XMLHttpRequest ist deutlich unauffälliger, außerdem werden die für den Angriff benötigten Cookies automatisch mitgeliefert. Das für die Durchführung der XMLHttpRequests notwendige "onreadystatechange" wurde von MySpace ausgefiltert und daher ebenfalls in einem eval()-Aufruf zusammengesetzt.
    Code: eval('xmlhttp.onread' + 'ystatechange = callback');

  8. Um Samy zur Liste der 'Heroes' des Opfers hinzuzufügen, musste ein POST-XMLHttpRequest an die addFriends-Seite unter www.myspace.com geschickt werden. Die aktuelle Seite befand sich jedoch unter profile.myspace.com, so dass der Request gegen die Same-Origin Policy verstößt. Um diese Einschränkung zu umgehen, nutzte Samy Kamkar aus, das die Profile sowohl unter profile.myspace.com als auch unter www.myspace.com erreichbar waren. Die Seite musste also nur unter der gewünschten Domain neu geladen werden.
    Code: if (location.hostname == 'profile.myspace.com') document.location = 'http://www.myspace.com' + location.pathname + location.search;

  9. Um Samy Kamkar zur Freundesliste des Opfers hinzuzufügen, fehlte nun nur noch ein entsprechender POST-XMLHttpRequest. Um CSRF-Angriffe zu verhindern, verwendete MySpace in seinen Formularen einen zufälligen Hash-Wert als Sicherheitstoken, der mit dem zugehörigen POST-Request abgesendet werden musste. Um diesen Hash-Wert zu erhalten, wurde vor dem Absenden des XMLHttpRequests eine Seite mit dem Hash-Wert über einen GET-Request geladen und daraus der Hash-Wert übernommen. Denn so ein Token schützt bekanntlich nur vor CSRF-Angriffen, wenn es nicht ausgespäht werden kann. Weshalb die geschützte Seite eben zum Beispiel keine XSS-Schwachstelle enthalten darf.

  10. Um den Wurmcode in die Profilseite des Opfers einzuschleusen, musste dieser erst passend codiert werden. Dazu wurde er von der aktuellen Seite gelesen und manuell passend angepasst. Die JavaScript-Funktionen für die URL-Kodierung und Escape behandelten nicht alle Fälle ausreichend. Weitere Probleme waren zum Beispiel die maximal mögliche Code-Länge, der teilweise Verzicht auf Leerzeichen, das Verbergen von Namen und die Wiederverwendung von Funktionen.

Wie Sie sehen können, besteht der Wurm aus ganz normalen JavaScript-Code, wenn auch teilweise in etwas unüblichen Schreibweisen - und an einer Stelle eingefügt, an der JavaScript eigentlich nichts zu Suchen hat.

Das der Wurm überhaupt funktionierte und sich auf MySpace ausbreiten konnte, hat zwei Gründe:

  1. Das Hauptproblem sind die unterschiedlichen Interpretationen des HTML- und JavaScript-Codes durch die verschiedenen Webbrowser: Wo der eine ein kaputtes CSS-Tag erkennt und folgerichtig ignoriert, sieht der andere JavaScript-Code, den er ausführt. Samy lief also nicht in allen Browsern, mit dem Internet Explorer aber in einem der verbreitetsten. Ohne, diesen Fehler der Browser wäre der Angriff fehl geschlagen.
  2. MySpaces Filter gegen XSS-Angriffe war zwar sehr gut, aber eben nicht gut genug war. Das Problem war einfach, das einige HTML-Tags zugelassen waren und andere nur auf eine Weise ausgefiltert wurden. Was wieder einmal den Nachteil von Blacklists zeigt: Was nicht drauf steht, wird durchgelassen. Wenn z.B. wie in diesem Fall 'innerHTML' verboten ist, hätte auch nach 'i'+'nnerHTML', 'in'+'nerHTML', ... 'i'+'n'+'nerHTML', ... usw. usf. gesucht werden müssen. Und alle möglichen anderen Kodierungen.

In der nächsten Folge geht es um eine weiter Art von XSS-Angriffe: DOM-basiertes XSS.

Carsten Eilers


Übersicht über alle Artikel zum Thema

Cross-Site Scripting im Überblick, Teil 1: Reflektiertes XSS
Cross-Site Scripting im Überblick, Teil 2: Persistentes XSS
Cross-Site Scripting im Überblick, Teil 3: Der MySpace-Wurm Samy
Angriffe über Cross-Site Scripting: Der Sourcecode des MySpace-Wurms Samy
Cross-Site Scripting im Überblick, Teil 4: DOM-basiertes XSS
Cross-Site Scripting im Überblick, Teil 5: Resident XSS
XSS-Angriffe, Teil 1: Informationen einschleusen
XSS-Angriffe, Teil 2: Cookies und Tastendrücke ausspähen
XSS-Angriffe, Teil 3: Zugangsdaten ausspähen
XSS-Angriffe, Teil 4: Ein Blick in die History, und dann auf ins LAN!
XSS-Angriffe, Teil 5: Ein Portscan (nicht nur) im LAN
XSS-Angriffe, Teil 6: Ein verbesserter Portscanner
XSS-Angriffe, Teil 7: Hindernisse beim JavaScript-Portscan beseitigen
XSS-Angriffe, Teil 8: Ein Portscan mit WebSockets oder Cross-Origin Requests
XSS-Angriffe, Teil 9: Der Router im Visier
XSS-Angriffe, Teil 10: Weitere Angriffe auf den Router
XSS-Angriffe, Teil 11: Unerwünschtes Firmware-Update für den Router
XSS-Angriffe, Teil 12: Browser-basierte Botnets
XSS-Angriffe, Teil 13: Fortgeschrittene Angriffe
XSS-Angriffe, Teil 14: Das Browser Exploitation Framework BeEF

Trackbacks

Dipl.-Inform. Carsten Eilers am : Drucksache: PHP Magazin 4.2015 - Cross-Side Request Forgery

Vorschau anzeigen
Im PHP Magazin 4.2015 ist ein Artikel über Cross-Site Request Forgery (CSRF) erschienen. Cross-Site Request Forgery (CSRF) ist eine sehr alte Schwachstelle. Das zu Grunde liegende Problem wurde erstmals 1988 unter dem Namen &quot;Confused Dep

Dipl.-Inform. Carsten Eilers am : Unerfreuliches zu Routern und dem IoT

Vorschau anzeigen
Es gibt mal wieder Neuigkeiten zu SOHO-Routern und verschiedenen Mitgliedern des IoT. Und natürlich keine guten, denn sonst würde ich sie hier ja nicht erwähnen. SOHO-Router im Visier... .... von Forschern... In SOHO-Route

Dipl.-Inform. Carsten Eilers am : Neues eBook: "Websecurity - Angriffe mit SSRF, CSRF und XML"

Vorschau anzeigen
Bei entwickler.press ist ein neues eBook von mir erschienen: &quot;Websecurity - Angriffe mit SSRF, CSRF und XML&quot; (ISBN: 978-3-86802-569-9, Preis: 2,99 €, erhältlich in den üblichen eBook-Shops). Der Shortcut beschäftigt sich

Dipl.-Inform. Carsten Eilers am : Die IoT Top 10, #1: Unsichere Weboberflächen, Teil 5

Vorschau anzeigen
Die Beschreibung der gefährlichsten Schwachstellen in den Geräten des IoT geht weiter. In der Liste der Top IoT Vulnerabilities von OWASP sind wir immer noch bei Platz 1, dem &quot;Insecure Web Interface&quot;. Aber wenigstens sind wir beim zweiten