Cross-Site Scripting im Überblick, Teil 4: DOM-basiertes XSS
Bisher ging es mit reflektierten und persistenten XSS um Angriffe, die über die Webanwendung auf dem Server laufen. Thema der heutigen Folge ist das DOM-basierte XSS, dass ausschließlich im Client-Code im Webbrowser abläuft.
Was ist DOM-basiertes XSS?
Erstmals beschrieben wurde DOM-basiertes XSS 2005 von Amit Klein.
Der Angriff spielt sich ausschließlich im Webbrowser ab, im Unterschied zu Angriffen über reflektiertes oder persistentes XSS ist der Schadcode niemals Bestandteil der vom Server gelieferten HTML-Daten. Weder der Server noch ein IDS/IPS oder eine Web Application Firewall können ihn darin also erkennen.
Der Client-seitige Code einer Webanwendung ist immer dann für
DOM-basiertes XSS anfällig, wenn sie Daten aus vom Angreifer
kontrollierbaren Objekten wie zum Beispiel document.location
,
document.URL
oder document.referrer
oder in
Zeiten von HTML5 und Web 2.0 auch irgend welche lokalen Eingaben ohne
Prüfung auf eingeschleusten Code verwendet. Das folgende Beispiel
folgt Amit Kleins Beispiel aus seinem
Paper.
DOM-basiertes XSS im Beispiel
Eine Webseite enthält den folgenden Code:
Hallo
<script>
var pos=document.URL.indexOf("name")+5;
document.write(document.URL.substring(pos,document.URL.length));
</script>
,<br>
Herzlich Willkommen auf dieser Seite ...
Beim Aufruf dieser Seite wird der Benutzer mit seinem Namen begrüßt, zum Beispiel beim Aufruf von
http://www.beispiel.example/index.html?name=Carsten
mit
Hallo Carsten,
Herzlich Willkommen auf dieser Seite ...
Der übliche XSS-Test mit
http://www.beispiel.example/index.html?name=<script>alert('XSS')</script>
führt dagegen zum Öffnen der Alertbox.
Dieses Beispiel funktioniert nicht, wenn der Webbrowser den URL selbständig URL-kodiert, wie es zum Beispiel Mozilla und Firefox tun. Dadurch werden die < und > zu %3C bzw. %3E, was die spätere Codeausführung verhindert. Die Umkodierung verhindert aber keine Angriffe, die nicht auf < und > angewiesen sind.
Der Angriff ist möglich, weil der Browser beim Aufruf des
präparierten URL einen HTTP-Request an
www.beispiel.example
sendet, die statische HTML-Seite mit
obigen Code darin empfängt und dann beginnt, die HTML-Daten in das DOM
zu parsen. Das DOM enthält das Objekt document
, das die
Eigenschaft URL
besitzt, in der der URL der aktuellen Seite
steht. Erreicht der Parser den JavaScript-Code, führt er ihn aus und
ändert entsprechenden den enthaltenen Anweisungen die Seite. Der Code
kopiert einen Teil des Inhalts von document.URL
in die
HTML-Seite. Im Beispiel also "Carsten
" - oder eben den
Schadcode
"<script>alert('XSS')</script>
". Das
Ergebnis sieht im zweiten Fall folgendermaßen aus:
Hallo <script>alert('XSS')</script>,
Willkommen auf dieser Seite ...
Die fertiggestellte HTML-Seite wird dann geparst - und dabei der eingeschleuste Skriptcode ausgeführt.
DOM-basiertes XSS tarnen
Wie bereits oben erwähnt ist der Schadcode nie Bestandteil der vom Server gelieferten HTML-Seite. Nur die im Request mitgelieferten Query-Daten verraten ihn, aber auch das kann umgangen werden. Dazu wird der Schadcode als Fragmentbezeichner getarnt:
http://www.beispiel.example/index.html#name=<script>alert('XSS')</script>
Das #-Zeichen markiert den darauf folgenden Rest des URL als Fragmentbezeichner. Der enthält Referenzierungs-Informationen, die vom Browser nach dem Empfang der Ressource lokal ausgewertet werden. Die meisten Browser senden den daher Fragmentbezeichner nicht an den Server, der dadurch nur
http://www.beispiel.example/index.html
zu sehen bekommt.
Dieser Trick funktioniert nicht immer. Zum Beispiel ist eine solche Tarnung
nicht möglich, wenn der Schadcode über den Benutzernamen oder das
Passwort eines URL nach dem Muster
http://Benutzername:Passwort@www.beispiel.example
eingeschleust wird. Der Schadcode wird dann als Bestandteil des
Authorization-Headers an den Server gesendet, wo er erkannt werden kann. Er
wird aber auch bei diesem Angriff nicht vom Server in die Antwort
eingebettet, das erledigt später der Browser beim Parsen der
empfangenen Seite.
Parameter-Prüfungen unterlaufen
Wird der zum Einschleusen des Schadcodes verwendete Parameter vom Server geprüft, kann er unter Umständen durch die Verwendung eines anderen Namens getarnt werden:
http://www.beispiel.example/index.html?noname=<script>alert('XSS')</script>
Der JavaScript-Code sucht nur nach dem String name
, dass da
in diesem Fall ein no
davor steht, stört ihn nicht.
Muss der Parameter name
vorhanden sein, zum Beispiel weil sein
Wert vom Server geprüft wird, kann er einfach an den URL mit dem
Parameter mit falschen Namen angehängt werden:
http://www.beispiel.example/index.html?noname=<script>alert('XSS')</script>&name=Carsten
Den Server stört der ihm unbekannte Parameter noname
nicht, er prüft wie vorgesehen den Wert des Parameters
name
. Der JavaScript-Code auf dem Client verwendet dagegen das
erste Vorkommen von name
- und das ist das in
noname
. Und damit kommt der XSS-Code in noname
zum Zuge und wird ausgeführt.
Darf name
nicht Bestandteil des zusätzlichen Parameters
sein, kann er evtl. über einen Parameter mit anderen, zulässigen
Namen getarnt werden:
http://www.beispiel.example/index.html?nix=name=<script>alert('XSS')</script>&name=Carsten
Der nicht verwendete Parameter nix
kommt zuerst, als dessen
Wert wird der für das Einschleusen verwendete Parameter samt Schadcode
verwendet: name=<script>alert('XSS')</script>
. Bei
der Auswertung durch den JavaScript-Code gilt das oben schon geschriebene:
In welchen Kontext das name
steht, ist egal. Nur sein
Vorkommen zählt.
Ü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 : Die IoT Top 10, #1: Unsichere Weboberflächen, Teil 5
Vorschau anzeigen
Dipl.-Inform. Carsten Eilers am : Der SDL am Beispiel eines Gästebuchs, Teil 6
Vorschau anzeigen