Learning XSS with Google’s XSS Game
Lépésről lépésre útmutató a Google’s XSS Game megoldásához

XSS aka Cross Site Scripting az egyik legveszélyesebb kliensoldali sebezhetőség és az egyik legkedveltebb hibavadászati módszer.
A Google XSS Game a Google által biztosított képzési platform az XSS gyakorlására. Ez áll 6 szintek és minden szinten, akkor kell végrehajtani egy JavaScript riasztás annak érdekében, hogy továbblépjen a következő szintre. Minden szinten különböző problémákat kap, és minden szinten különböző technikákkal kell végrehajtania a riasztást. Ez segít megérteni a különböző módszereket, amelyekkel XSS-t lehet végrehajtani egy weboldalon.
Szerint kezdjük el.
Navigáljon a https://xss-game.appspot.com címre. Itt elérhető a Google XSS játék.
Egy ilyen oldalt fog látni

Kattintson a Let me at ’em! hogy belépjen a játékba.
Első feladat : Hello world of XSS

A virtuális böngészőbe kell az xss payloadot befecskendeznie. A forráskódot a “toggle” linkre kattintva tekintheti meg. Ha nem sikerül az injektálás, akkor a “show” linkre kattintva kaphatsz tippeket.
A forráskód ellenőrzése közben kiderül, hogy ez egy python szkript, és a függvénydef get(self)
2 érdekes része a
self.response.headers.add_header("X-XSS-Protection", "0")
és
query = self.request.get('query', '')
message = "Sorry, no results were found for <b>" + query + "</b>."
message += " <a href='?'>Try again</a>."
Az első rész kikapcsolja a chrome XSS auditorát, és lehetővé teszi számunkra az XSS payload injektálását a böngészőben.
A második rész azt mutatja, hogy az url param query
értéke közvetlenül a testhez kerül. Ezt kell kihasználnunk.
Ez egy egyszerű, és megpróbálhatod beírni az alábbiak bármelyikét (és még több is van) a keresőmezőbe, és keresni
<a href="javascript:alert()">Link</a>
<img src=X onerror="alert()">
<script>alert()</script>
És így tovább. Ha az elsőt használtad, akkor a Linkre kell kattintanod a riasztás végrehajtásához.
Nagyszerű!!! Sikeresen teljesítetted az 1. szintet. Most egy gombot fogsz látni, amellyel a következő szintre léphetsz.
Második feladat : A kitartás a kulcs

Ebben a feladatban egy poszt hozzáadásával kell végrehajtanod a riasztást. Ebben a játékban ez DOM XSS, de ha valódi chat/kommentáló alkalmazásokon teszteljük, akkor ez egy tárolt XSS lesz.
Oké, nézzük meg a forrást és az előző üzenetet is.
A forrás vizsgálatakor láthatjuk, hogy az alapértelmezett üzenet különböző típusú html tageket használ a stílushoz. Ez a mi kulcsunk.
Vizsgáljuk meg a forrást, hogy ezt megerősítsük. Így jelenik meg a bejegyzésünk
Láthatjuk, hogy a bejegyzés nem megy át semmilyen szűrőn. Tehát bármelyik fent említett módszert használhatjuk.
<a href="javascript:alert()">Link</a>
<img src=X onerror="alert()">
És így tovább.
Gratulálunk. Teljesítetted a 2. szintet. Most lépj tovább a következő szintre.
3. feladat : Az a süllyedő érzés

Ez csendben különbözik a 2-től, amit már teljesítettünk. Itt meg kell tanulnunk a window.location.hash.
-t. Ez a #
szimbólum után következő rész, és az oldalon belüli navigációhoz használják. Ez egy böngészőfunkció, és JavaScript nélkül is működik.
Vizsgáljuk meg ennek a forráskódját.
A kód érdekes része
var html = "Image " + parseInt(num) + "<br>";
html += "<img src='https://medium.com/static/level3/cloud" + num + ".jpg' />";
num
a window.location.hash
értékét tartja, és 2 helyen használják. Az első helyen a parseInt függvényen belül használják, ezért a mi payloadunk ott nem fog működni. A következő sorban azonban a nyers adatot használjuk. Ez az a hely, ahová be fogjuk injektálni a payloadunkat.
Szóval ott kell bezárnunk egyetlen idézőjelet '
és be kell injektálnunk a payloadunkat.
Kipróbálhatsz bármilyen payloadot a ' '
belsejében #
Kipróbálhatod, hogy a #
után az alábbiak közül bármelyiket beteszed és meglátogatod az url-t.
1' onerror='alert()
1'><img src=X onerror="alert()">'
1'><script>alert()</script>'
1'><a href="javascript:alert()">Link</a>'
És így tovább.
Nagyszerű. Most már továbbléphetünk a következő szintre.
A 4. feladat : A kontextus számít

Az időzítő időtartamának megadására van hely. Ezt fogjuk kihasználni.
Nézzük meg a forráskódot.
A timer.html-ben ezt a sort láthatjuk
<img src="https://medium.com/static/loading.gif" onload="startTimer('{{ timer }}');" />
Az {{ timer }}
kifejezésben kell kihasználnunk, de ez egy startTimer('');
függvényben van elhelyezve, ami egy onload
esemény kezelője. A fő szempont, hogy a HTML-ben az eseménykezelő attribútum több visszahívási függvényt is elfogad.
Ezért be kell zárnunk a függvényt, és ott kell végrehajtanunk a figyelmeztetésünket. Vegye figyelembe, hogy az értéket nem egy parseInt
függvényen keresztül adtuk át, hanem a nyers adatokat használjuk. Tehát lezárhatjuk a függvényt egy ');
hozzáadásával, majd beilleszthetjük a alert
-unkat. Mivel inline-ként van használva, nem injektálhatjuk oda a alert();
-t, mert az tönkretenné a dolgokat. Az utasítás onload="startTimer('3'); alert();')"
lesz, és nem fog működni.
Ezért hozzá kell adnunk egy mintát, hogy a minta ne törjön meg.
Adjunk hozzá alert('
és ez elég.
Szóval a payloadunk a következő lesz
3');alert('
Az időzítő indítása gombra kattintva végrehajtjuk a riasztást és ezzel befejeztük ezt a szintet.
Előrelépés a következő feladathoz.
Feladat 5 : A protokoll megtörése

A kezdőlapon nincs módunk semmit beadni. Csak egy linkünk van. Tehát kattintsunk rá.
Itt 2 helyet láthatunk, ahová bejuttathatjuk a hasznos terhelésünket. egyet magán az url-en, egyet pedig a beviteli mezőn. A beviteli mező egy olyan hely, ahová beírhatjuk az e-mail címünket, és reméljük, hogy az nem fog máshol visszatükröződni. Tehát menjünk az elsőhöz. Az url-en.
Nézzük meg az aktuális pag forráskódját, azaz a signup.html-t, és láthatjuk a sort
<a href="{{ next }}">Next >></a>
Nagyszerű hely a payload befecskendezésére. A mi payloadunk a href
attribútum értékeként lesz beállítva egy a
tagben. Ha képesek vagyunk a javascript:alert()
hozzáadására, akkor végre tudjuk hajtani a hasznos terhelésünket. Most nézzük meg, hogy mi az next
értéke. Nem találunk ilyet az oldalon. Hol keressük?
Python kód a segítségünkre. Nézzük meg a level.py-t, és látni fogjuk
if "signup" in self.request.path:
self.render_template('signup.html',
{'next': self.request.get('next')})
Az url-ben szereplő next
értékét fogjuk használni.
Változtassuk meg az next
értékét az url-ben confirm
-ről javascript:alert()
-re és a végleges url így fog kinézni
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
és a függvénytestben a következő kódot láthatjuk.
var scriptEl = document.createElement('script');
Szóval külső js fájlt tudunk betölteni, de nem http
vagy https
url-ből.
Itt próbáljuk ki a data
urlokat.
Az adat urlok data:{type},content
Az #
utáni értéket tehát módosítsuk
data:application/javascript,alert()
vagy
data:text/plain,alert()
-re, és a alert
-t végre tudjuk hajtani.
Itt van egy videó a játék megoldásáról.