SQL Injection โ High
Op het hoge niveau probeert de applicatie je aanval af te weren door het invulveld op een compleet andere pagina te zetten.
1. Predict (Voorspel)โ
Wanneer je op "Click here to change your ID" klikt, opent een pop-up. Je vult daar je ID in. De server slaat dit op in een sessie-variabele: $_SESSION['id'] = $id;.
Vervolgens keer je terug naar de originele pagina en voert de applicatie de volgende query uit:
$id = $_SESSION[ 'id' ];
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
Vraag: Waarom dacht de ontwikkelaar dat dit veiliger was? Heeft hij gelijk?
Antwoord
De ontwikkelaar dacht: "Als het invulveld niet op dezelfde pagina staat als de database-query, kunnen geautomatiseerde aanvalstools de pagina moeilijker raken."
Hij heeft ongelijk. De invoer uit de pop-up wordt nog steeds ongefilterd in $id gezet en rechtstreeks in de query geplakt. De kwetsbaarheid bestaat nog โ ze is alleen รฉรฉn klik dieper verstopt. Dit heet Security by Obscurity: verstoppen in plaats van echt beveiligen.
2. Run (Uitvoeren)โ
Start het lab en verken de interface.
Klik op de link "Click here to change your ID". Vul 1, 2 en 3 in en observeer telkens het resultaat op de hoofdpagina.
3. Investigate (Onderzoeken)โ
Probeer nu je payload van het Low level (1' OR '1'='1) in te vullen in de pop-up en klik op Submit.
Vraag: Hoeveel gebruikers zie je? Vergelijk dit met het Low level โ wat is er anders? Wat in de SQL query uit ยง1 veroorzaakt dit verschil?
Antwoord
Je ziet maar 1 gebruiker in plaats van alle 5. De LIMIT 1 aan het eind van de query beperkt het aantal resultaten, ook al is de OR-conditie geldig.
De query wordt:
SELECT ... WHERE user_id = '1' OR '1'='1' LIMIT 1;
De database geeft braaf alle rijen terug โ maar kapt dan af bij 1.
De vraag is nu: hoe zorg je ervoor dat LIMIT 1 genegeerd wordt? In SQL bestaat een manier om de rest van een regel onzichtbaar te maken voor de database-parser.
4. Modify & Make (Aanpassen & Maken)โ
Je weet dat LIMIT 1 de output beperkt. Jouw doel: neutraliseer LIMIT 1 zodat alle gebruikers zichtbaar worden.
In SQL bestaat een mechanisme om alles na een bepaald teken te negeren โ net zoals // een commentaar start in JavaScript.
Tip
In MySQL start een commentaar met # of met -- (twee streepjes + spatie). Alles wat daarna komt op dezelfde regel, wordt door de database genegeerd. Voeg dit toe aan het einde van je payload zodat LIMIT 1 buiten de 'actieve' query valt.
Antwoord
Vul in de pop-up in: 1' OR '1'='1' #
De database ziet dan:
SELECT ... WHERE user_id = '1' OR '1'='1' #' LIMIT 1;
Alles na # (inclusief LIMIT 1) wordt genegeerd. Alle 5 gebruikers verschijnen.
5. โ Wat moest je zien?โ
- Er verschijnt een lijst met alle 5 gebruikers ondanks de
LIMIT 1beperking. - Alles na het
#in jouw payload wordt door de database genegeerd โ inclusiefLIMIT 1. - Het invulveld zat in een pop-up, maar de kwetsbaarheid was er gewoon nog.
Zie je maar รฉรฉn resultaat? Controleer of je # aan het einde van je payload hebt en er geen extra spatie vรณรณr het # staat.