Welkom bij de cursus Web Application Security! Deze cursus gaan we ons richten op het hacken van websites. En met die zin komen we meteen bij een gouden regel:
Het hacken van websites zonder toestemming is niet toegestaan
Om de opdrachten te kunnen maken krijg je toestemming om de websites in de VM te mogen hacken ;). We gaan in verschillende manieren bekijken om in te breken op een website. Aan jullie de taak om die tijdens de workshop in de praktijk te brengen
We beginnen bij één van de meest veelvoorkomende beveiligingslekken die er bij webapplicaties voorkomen. Dagelijks nog zijn er nieuwsberichten van websites die hun code niet goed op orde hebben en kwetsbaar zijn tegen deze aanval. Deze week gaan we kijken hoe deze aanval werkt en hoe je er tegen kunt beveiligen.
In bijna alle webapplicatie projecten heb je te maken met een database waar je mee communiceert via SQL. Een typische query die wordt uitgevoerd is bijvoorbeeld deze:
SELECT * FROM leden WHERE naam='paul' AND heeftbetaald='ja'
Waarbij het blauwe gedeelte invoer is uit bijvoorbeeld een GET parameter ('?naam=paul'). Er lijkt niks aan de hand, maar als we de invoer niet zorgvuldig filteren geven de gebruiker de kans om de query op onbedoelde manier te veranderen.
Met
--
(streepje, streepje, spatie) is het in SQL mogelijk om commentaar te zetten in je query, hetzelfde wat je in PHP met
//
zou doen. Met een slim gekozen invoer kunnen we de query er zo uit laten zien:
SELECT * FROM leden WHERE naam='paul' -- ' AND heeftbetaald='ja'
De database voert de query uit, maar niet zoals de gebruiker hem heeft bedoeld: alles achter de -- wordt genegeerd als commentaar. De query zal dus ook rijen teruggeven waar heeftbetaald niet op 'ja' staat, wat afhankelijk van de code van de website kan betekenen dat we gratis dingen kunnen kopen :)
Een andere manier om queries te veranderen is om nieuwe logica (AND, OR) te injecteren in de SQL. We kunnen bijvoorbeeld de volgende query maken met de juiste invoer:
SELECT * FROM leden WHERE naam='paul' OR 'bla'='' AND heeftbetaald='ja'
Deze query maakt weer het
heeftbetaald='ja' gedeelte nutteloos. Als de naam al overeenkomt maakt het niet uit wat er achter de OR staat, het
resultaat is altijd true (de haakjes worden als volgt geplaatst:
. OR ( . AND . )
).
Eén van de meest gevaarlijke is als het mogelijk is om compleet nieuwe queries uit te kunnen voeren op de database. Bedenk eens wat er gebeurt als de gebruiker deze invoer geeft:
SELECT naam FROM leden WHERE id=0; DROP TABLE leden;
Met
;
geven we aan dat we een nieuwe query beginnen, waarna we vervolgens vrij zijn om elke query uit te voeren die we maar
willen. Let wel dat het uitvoeren van meerdere queries met bijvoorbeeld mysqli_query() iets is wat standaard uit staat.
Deze techniek is extra gevaarlijk omdat deze immuun is tegen escapen als het invoer is die niet tussen quotejes staat.
We kunnen met behulp van de UNION operator ook informatie halen uit andere tabellen in de database:
SELECT naam FROM leden WHERE id=0 UNION SELECT wachtwoord FROM admins
De query haalt nu namen van leden op, samen met wachtwoorden uit de admins tabel. Belangrijk voor de UNION is dat beide queries evenveel kolommen teruggeven.
Het is niet moeilijk om bovenstaande aanvallen te voorkomen. Met een paar simpele aanpassingen kan je ervoor zorgen dat je SQL altijd wordt uitgevoerd zoals je die bedoeld hebt.
Je slaat de SQL op als stored procedure in de database en roept deze aan vanuit je code. Omdat de SQL in de database staat in plaats op de server is SQL injectie niet mogelijk
Dit is de meest gebruikte en veilige manier. Met vraagtekentjes geef je aan op welke plekken de invoer moet komen en die vul je dan later in. De SQL wordt altijd uitgevoerd zoals je hem bedoeld hebt. En ook hier is SQL injectie onmogelijk. Lees hier verder
Je kan ook alle invoer zelf escapen met functies zoals mysqli_real_escape_string(). Zorg ervoor dat je dan consequent alle strings escaped met die functie en alle getallen cast naar int's voordat je ze in je SQL plakt. Als je er ook maar eentje mist heb je al een SQL injection mogelijkheid op je website!
Op deze site kan je het allemaal extra nalezen. Maar voor nu genoeg theorie, let's HACK!
Bob is al jaren trouwe klant en gebruikt de site dagelijks om te kijken hoeveel geld er op zijn rekening staat. Achter op zijn poespas pas heeft hij met een viltstift „Niet vergeten: Bob 123456” geschreven. Gebruik de site om te kijken hoeveel geld Bob op zijn rekening heeft staan.
Alice is ook klant van de bank en wij willen ook graag weten hoeveel geld zij op haar rekening heeft staan. We gaan daarom haar rekening hacken met behulp van SQL.
Ga nu aan de slag en hack het account van Alice! Gebruik hiervoor de bovenste link "Bank" op de startpagina van jouw virtuele machine.
Hint 1: Kijk eerst eens wat er gebeurt als je inlogt met een enkele quote in de gebruikersnaam (').
Hint 2: Met -- (twee streepjes gevolgd door een spatie) kan je commentaar achter een regel zetten in SQL.
Hint 3: Bekijk de broncode achter de site: https://git.paulwagener.nl/Paul/Security-VM/src/master/bank/index.php#L51 De code beschouwt een gebruiker als ingelogd als de query een rij uit de gebruikerstabel teruggeeft. Manipuleer de query zodat deze de gegevens van Alice teruggeeft, zonder dat je het wachtwoord hoeft te weten.
Waarschijnlijk heb je SQL commentaar (--) gebruikt in de vorige opdracht. Voer nu een andere SQL injectie uit door alleen het wachtwoord veld te gebruiken. Gebruik niet de SQL commentaar techniek maar verander nu de logica van de query (AND, OR) zodat er niet meer gecontroleerd wordt op het wachtwoord.
Hint: Maak er een query van die alle gebruikers teruggeeft, de site logt dan in als de eerste gebruiker.
Open de "Bank (multi_query)" pagina. Op deze pagina werken ook SQL Injection technieken die gebruik maken van meerdere queries (queries gescheiden door een ; ).
Inloggen in een ander account is leuk. Maar echte hackers stelen kostbare data uit een website. Dat gaan we nu doen met de webshop van Leaky's. Gebruik hiervoor de link "Webshop" op de startpagina van jouw virtuele machine.
Je kan de broncode vinden op: https://git.paulwagener.nl/Paul/Security-VM/src/master/webshop/product_detail.php#L62
Zoals je ziet hebben ze hier gebruik gemaakt van mysqli::real_escape_string(). Je kan dus geen gebruik meer maken van rare quotejes om de query aan te passen.
Maar met behulp van de UNION techniek kunnen we alsnog data stelen uit de website.
In de database is er nog een tabel "gebruikers" waar gebruikersnamen en wachtwoorden in staan. Steel deze informatie uit de database!
Hint: Verander het cijfer in de url van de product_details.php pagina in de letter 'a' zodat je de query kan lezen.
Open de pagina "Webshop (replace)". De maker van deze website heeft extra maatregelen genomen en woorden als SELECT en UNION uit de invoer gefilterd.
Hint: SELSELECTECT
Ga in de VM naar de "Wereldwijs" pagina. Op deze pagina kunnen studenten op spelenderwijs leren over de wereld. Maar deze site heeft een diep donker geheim die het niet toont aan de wereld, er is een geheime pagina met id 0.
Geen hints en geen broncode deze keer. Aan jullie de taak om de site te hacken (meerdere manieren mogelijk).