Wat als een paar seconden vertraging al genoeg zijn om gevoelige informatie uit een systeem te halen? Soms hoeft een aanvaller geen data direct te zien om een database leeg te trekken. Alleen het meten van reactietijden kan al voldoende zijn.
In What the Hack delen onze hackers opvallende kwetsbaarheden uit anonieme penetratietesten. Zo krijg je als developer inzicht in hoe kwetsbaarheden in de praktijk worden uitgebuit en belangrijker nog: hoe je ze voorkomt. In deze editie laat Daan zien hoe hij met Time-Based SQL Injection toegang krijgt tot een database en hoe developers deze kwetsbaarheid kunnen herkennen en voorkomen.
De penetratietest voerde ik uit op een applicatie die zeer gevoelige en persoonlijke gegevens verwerkte. Zoals bij elke test startte ik het onderzoek met een verkenning van het systeem.
Voor het analyseren van het webverkeer gebruikte ik BurpSuite Professional. Deze tool is voor pentesters als een Zwitsers zakmes: hij analyseert, manipuleert en scant het het webverkeer automatisch op kwetsbaarheden.
Automatische scans zijn een hulpmiddel. Ze signaleren mogelijke problemen, maar het is altijd aan de tester om te controleren of er daadwerkelijk sprake is van een kwetsbaarheid.
Tijdens de scan verscheen een melding bij het endpoint dat verantwoordelijk was voor de jaaropgaven: ‘SQL Injection’
Dit soort meldingen zien we vaker tijdens penetratietesten en zijn regelmatig false positives. Soms reageert een server bijvoorbeeld wat trager door hoge belasting, waardoor een scanner denkt dat het een kwetsbaarheid is. Toch wilde ik dit signaal verder onderzoeken.
Een van de manieren om SQL-injectie te detecteren, is door te kijken naar tijdvertragingen in databasequeries.
Vrijwel elke database bevat functies waarmee een query tijdelijk kan worden gepauzeerd. Ontwikkelaars gebruiken dit soms om te testen hoe een applicatie reageert wanneer een databaseactie langer duurt. Een aanvaller kan dit mechanisme misbruiken.
Door een query zo aan te passen dat de database bijvoorbeeld een aantal seconden wacht voordat deze reageert, kan een aanvaller bepalen of gebruikersinvoer daadwerkelijk invloed heeft op de query. Als de responstijd precies overeenkomt met de ingestelde vertraging, is dat een sterke indicatie dat de invoer in de SQL-query terechtkomt.
Om dit te testen dubliceerde ik het webverzoek uit de melding en paste het aan. In plaats van een vertraging van 3 seconden werd de query zo aangepast dat de database 50 seconden moest wachten voordat deze antwoord gaf.
Dit kan uitsluiten dat de vertraging toevallig wordt veroorzaakt door serverbelasting. Het antwoord kwam exact 50 seconden later terug. Een bevestiging dat de applicatie daadwerkelijk kwetsbaar was voor Time-Based SQL Injection.
Het is mogelijk om de databasegegevens handmatig uit te lezen via tijdgebaseerde injecties, maar dat is een langzaam proces. Daarom gebruikte ik een SQLmap. SQLmap automatiseert het volledige proces van detectie tot exploitatie en kan via tijdgebaseerde queries stap voor stap data uit een database reconstrueren.
Het resultaat? Toegang tot de database met daarin ongeveer 1200+ organisaties. De database bevatte bovendien gevoelige persoonsgegevens, waaronder BSN-nummers, adresgegevens en gebruikersinformatie.
Verder in de analyse bleek dat drie verschillende parameters in de applicatie kwetsbaar waren voor SQL-injectie. Voor de aanval was één parameter al voldoende om volledige database-toegang te verkrijgen.
De kwetsbaarheid had relatief eenvoudig voorkomen kunnen worden door het gebruik van prepared statements (ook wel parameterized queries genoemd).
Prepared statements zorgen ervoor dat:
Hierdoor kan een aanvaller geen extra SQL-commando’s injecteren en blijft de databasequery veilig.
De kwetsbaarheid werd gedetecteert door een automatische scanner. Zonder handmatige verificatie was deze melding mogelijk een false positive. Scanners signaleren afwijkingen, maar de tester bepaalt of er daadwerkelijk sprake is van een exploitbare kwetsbaarheid.
Voor organisaties onderstreept dit opnieuw het belang van:
Soms is één kwetsbare parameter al voldoende om een hele database bloot te leggen.