Articles

XSS lernen mit Googles XSS-Spiel

Schrittweise Anleitung, wie man Googles XSS-Spiel löst

Foto von Markus Spiske temporausch.com from Pexels

XSS aka Cross Site Scripting ist eine der gefährlichsten clientseitigen Schwachstellen und eine der beliebtesten Methoden zur Fehlersuche.

Google XSS Game ist eine Trainingsplattform von Google, um XSS zu üben. Es besteht aus 6 Levels und in jedem Level müssen Sie einen JavaScript-Alarm ausführen, um zum nächsten Level zu gelangen. In jedem Level werden Sie mit verschiedenen Problemen konfrontiert, und Sie müssen den Alarm mit verschiedenen Techniken in jedem Level ausführen. Dies wird Ihnen helfen, verschiedene Methoden zu verstehen, die zur Ausführung von XSS in einer Webseite verwendet werden können.

Legen wir also los.

Navigieren Sie zu https://xss-game.appspot.com. Hier ist das Google XSS-Spiel verfügbar.

Sie werden eine Seite wie diese sehen

Klicken Sie auf die Schaltfläche Let me at ‚em! um in das Spiel einzusteigen.

Erste Aufgabe: Hello world of XSS

Sie müssen den XSS-Payload in den virtuellen Browser injizieren. Sie können den Quellcode anzeigen, indem Sie auf den Link „toggle“ klicken. Wenn Sie nicht in der Lage sind, zu injizieren, können Sie die Hinweise erhalten, indem Sie auf den Link „show“ klicken.

Während Sie den Quellcode überprüfen, ist es ein Python-Skript und die 2 interessanten Teile in der Funktion
def get(self) sind

self.response.headers.add_header("X-XSS-Protection", "0")

und

query = self.request.get('query', '')
message = "Sorry, no results were found for <b>" + query + "</b>."
message += " <a href='?'>Try again</a>."

Der erste Teil wird den Chrome XSS-Auditor ausschalten und uns erlauben, die XSS-Nutzlast in den Browser zu injizieren.

Der zweite Teil zeigt, dass der Wert des Url-Parameters query direkt in den Body eingefügt wird. Das ist der Punkt, den wir ausnutzen müssen.

Dies ist ein einfacher und Sie können versuchen, eine der folgenden (und noch mehr gibt es) in das Suchfeld einzugeben und sie zu durchsuchen

<a href="javascript:alert()">Link</a>

<img src=X onerror="alert()">

<script>alert()</script>

Und so weiter. Wenn du die erste benutzt hast, musst du auf den Link klicken, um den Alarm auszuführen.

Gut!!! Du hast Level 1 erfolgreich abgeschlossen. Jetzt siehst du einen Button, um zum nächsten Level zu gelangen.

Zweite Aufgabe: Ausdauer ist der Schlüssel

In dieser Aufgabe musst du eine Meldung ausführen, indem du einen Beitrag hinzufügst. In diesem Spiel handelt es sich um DOM XSS, aber wenn man es in echten Chat-/Kommentaranwendungen testet, wird es ein gespeichertes XSS sein.

Schauen wir uns den Quelltext und die vorherige Nachricht an.

Bei der Untersuchung des Quelltextes kann man sehen, dass die Standardnachricht verschiedene Arten von HTML-Tags verwendet, um sie zu gestalten. Das ist unser Schlüssel.

Überprüfen Sie den Quelltext, um dies zu bestätigen. So wird unser Beitrag gerendert

Sie können sehen, dass der Beitrag keine Filter durchläuft. Wir können also jede der oben genannten Methoden verwenden.

<a href="javascript:alert()">Link</a>

<img src=X onerror="alert()">

Und so weiter.

Glückwunsch. Du hast Level 2 abgeschlossen. Jetzt gehst du zum nächsten Level.

Aufgabe 3: Das Gefühl des Versinkens

Dies ist ganz anders als die 2, die wir abgeschlossen haben. Hier müssen wir etwas über window.location.hash. lernen. Es ist der Teil, der nach dem #-Symbol kommt und für die seiteninterne Navigation verwendet wird. Es handelt sich um eine Browserfunktion, die auch ohne JavaScript funktioniert.

Schauen wir uns den Quellcode an.

Der interessante Teil des Codes ist

var html = "Image " + parseInt(num) + "<br>";
html += "<img src='https://medium.com/static/level3/cloud" + num + ".jpg' />";

num, der den Wert von window.location.hash enthält und an zwei Stellen verwendet wird. An der ersten Stelle wird er innerhalb der parseInt-Funktion verwendet, so dass unsere Nutzlast dort nicht funktionieren wird. Aber in der nächsten Zeile werden die Rohdaten verwendet. Dort werden wir unsere Nutzdaten einfügen.

So müssen wir dort ein einzelnes quot ' schließen und unsere Nutzdaten einfügen.

Sie können jede beliebige Nutzlast innerhalb von ' ' nach #

Versuchen Sie, eine der folgenden nach # zu setzen und die URL zu besuchen.

1' onerror='alert()

1'><img src=X onerror="alert()">'

1'><script>alert()</script>'

1'><a href="javascript:alert()">Link</a>'
Und so weiter.

Gut. Jetzt können wir zur nächsten Stufe übergehen.

Aufgabe 4: Der Kontext zählt

Wir haben ein Feld, um die Dauer des Timers einzugeben. Das werden wir ausnutzen.

Schauen wir uns den Quellcode an.

In timer.html sehen wir diese Zeile

<img src="https://medium.com/static/loading.gif" onload="startTimer('{{ timer }}');" />

Wir müssen den Ausdruck {{ timer }} ausnutzen, aber er befindet sich innerhalb einer Funktion startTimer('');, die ein Event-Handler für das Ereignis onload ist. Der wichtigste Punkt ist, dass das Event-Handler-Attribut in HTML mehrere Callback-Funktionen akzeptiert.

So müssen wir die Funktion schließen und unseren Alarm dort ausführen. Beachten Sie, dass der Wert nicht durch eine parseInt-Funktion übergeben wurde, sondern die Rohdaten verwendet werden. Wir können also die Funktion durch Hinzufügen eines '); schließen und dann unser alert einfügen. Da die Funktion als Inline-Funktion verwendet wird, können wir alert(); dort nicht einfügen, da dies zu Problemen führen würde. Die Anweisung wird zu onload="startTimer('3'); alert();')" und es wird nicht funktionieren.

So müssen wir ein Muster hinzufügen, das das Muster ungebrochen hält.
Fügen Sie alert(' hinzu und es ist genug.

So wird unsere Nutzlast sein

3');alert('

Klicken Sie auf die Schaltfläche „Start Timer“, um den Alarm auszuführen und wir haben dieses Level beendet.

Weiter zur nächsten Aufgabe.

Aufgabe 5 : Breaking Protocol

Auf der Startseite haben wir keine Möglichkeit, etwas einzuschleusen. Alles, was wir haben, ist ein Link. Klicken wir also darauf.

Hier sehen wir zwei Stellen, an denen wir unsere Nutzlast einschleusen können: eine auf der URL selbst und eine auf dem Eingabefeld. In das Eingabefeld kann man seine E-Mail eingeben und hoffen, dass sie nicht irgendwo anders wiedergegeben wird. Gehen wir also zur ersten Stelle. Auf der url.

Inspektieren Sie den Quellcode der aktuellen Seite, das ist signup.html und wir können die Zeile

<a href="{{ next }}">Next >></a>

Großartiger Ort, um eine Nutzlast zu injizieren. Unsere Nutzlast wird als Wert des Attributs href in einem a-Tag gesetzt. Wenn wir in der Lage sind, javascript:alert() hinzuzufügen, können wir unseren Payload ausführen. Nun wollen wir sehen, was der Wert von next ist. Wir können keinen auf der Seite finden. Wo können wir danach suchen?

Python-Code zur Rettung. Schauen wir uns level.py an, sehen wir

if "signup" in self.request.path:
self.render_template('signup.html',
{'next': self.request.get('next')})

So wird der Wert von next in der Url verwendet.

Ändern Sie den Wert von next in der URL von confirm auf javascript:alert() und die endgültige URL wird wie folgt aussehen

Now clicking on Next >> in the page will trigger our payload.

We now completed level 5. And 1 level remains.

Task 6 : Follow the 🐇

There is a path to a js file in the url.

Let’s inspect the source code. In page index.html, you can see a function includeGadget und innerhalb des Funktionskörpers können Sie den folgenden Code sehen.

var scriptEl = document.createElement('script');

So können wir externe js-Dateien laden, aber nicht von einer http oder https URL.

Hier probieren wir die data urls.

Daten urls sind in der Form data:{type},content

So ändern wir den Wert nach # zu

data:application/javascript,alert()

oder zu

data:text/plain,alert() und wir können die alert ausführen.

Hier ist ein Video zum Lösen des Spiels.