Wat SQL-aanvallen zo populair en efficiënt maakt

Ondanks verbeteringen in beveiligingshard- en software blijft een SQL-aanval een populaire vector voor hackers. Je leest al te vaak dat een hacker via een SQL-injectie de controle krijgt over data, maar wat betekent dat precies?

SQL-injecties zijn sinds jaar en dag een populaire vector voor aanvallers die via de applicatielaag toegang willen tot gegevens van een doelwit. Hoewel beveiliging jaar na jaar geavanceerder wordt, blijven SQL-aanvallen in het nieuws opduiken. Waarover gaat het precies wanneer er een SQL-kwetsbaarheid wordt ontdekt?

Praten met een database

Ontwikkelaars met database-ervaring weten ongetwijfeld wat het probleem precies is, maar voor lezers zonder expertise beginnen we bij het begin. SQL, kort voor Structured Query Language, is een taal gebouwd voor het beheer van redactionele databases. SQL is database-agnostisch: de programmeertaal is een standaard in de industrie die werkt over zowat alle databaseproducten van verschillende verkopers heen. Wie SQL spreekt, heeft met andere woorden de vocabulaire om met databases overal ter lande te spreken.

SQL maakt gebruik van query’s waarmee een gebruiker data kan opvragen, aanpassen of verwijderen. Dergelijke query’s bevatten eenvoudige syntax, die compatibel is met booleaanse expressies. Die laatste ken je zeker: AND, NOT en OR zijn dergelijke expressies en ze vormen de basis van computerlogica. Een eenvoudig voorbeeld van een query is:

  • SELECT id FROM gebruikers WHERE gebruikersnaam= ‘gebruikersnaam’ AND wachtwoord=’wachtwoord’

Dat is een voorbeeld van een eenvoudige authenticatie via SQL. Via de query vraagt de gebruiker aan een database om een ID op te halen uit de tabel genaamd gebruikers. Het ID wordt bepaald aan de hand van de gebruikersnaam en het wachtwoord. De waardes tussen aanhalingstekens zijn in dit voorbeeld variabelen die de gebruiker zelf moet ingeven. Ze zijn afkomstig van bijvoorbeeld een loginvenster voor een webapplicatie.

Van goede trouw naar injectie

SQL gaat hand in hand met dergelijke applicaties. De taal laat een toepassing toe om een bepaalde database te gebruiken. Het probleem van SQL-injectie wordt duidelijk wanneer je kijkt naar wat een externe gebruiker allemaal zelf kan invullen. In ons voorbeeld is het aan diegene die de webapplicatie wenst te gebruiken om zijn gebruikersnaam en wachtwoord in te geven in de daartoe bestemde velden. De input wordt in de query gepompt waarna de server die uitvoert.

Zolang iedereen ter goeder trouw is, is er geen probleem. Juiste combinaties van namen en wachtwoorden leveren een ID op, bij foute combinaties is er geen resultaat voor de query. Wil mijnheer Florimond met wachtwoord: Florre15 inloggen in de database, dan wordt de query als volgt:

  • SELECT id FROM gebruikers WHERE gebruikersnaam= ‘Florimond’ AND wachtwoord=’Florre15’

Tot zover loopt alles zoals verwacht. Wat nu wanneer Florimond geen account heeft en zijn hackerspet opzet? Als wachtwoord kan hij intypen hackz0rz’ OR 1=1’. Dit is het éénvoudigste voorbeeld van een SQL-injectie-aanval.

De aanvaller typt niet gewoon tekst in het wachtwoordveld, maar volgt die tekst op met een aanhalingsteken (), gevolgd door de booleaanse operator OR en een eenvoudig statement: 1=1. Pas dan sluit hij de input af. De input wordt net als in een legitiem scenario in de query geïnjecteerd, met het volgende resultaat:

  • SELECT id FROM gebruikers WHERE gebruikersnaam= ‘Florimond AND wachtwoord=’hackzOrz’ OR 1=1’

Deze query krijgt plots een heel andere betekenis. Het stukje SQL-code vraagt de database om het gebruikers-ID door te geven voor een combinatie van gebruikersnaam en wachtwoord wanneer die kloppen. De operator OR breidt de instructie echter uit. Als de naam- en wachtwoordcombinatie niet klopt, mag de database ook een ID geven wanneer het daaropvolgende statement klopt. Dat statement (1=1), is altijd juist. De database zal nu het allereerste gebruikers-ID in de database als antwoord geven. Al te vaak is dat ID gekoppeld aan de administrator van de database. Florimond heeft nu zonder de juiste credentials via SQL-injectie administratortoegang tot een database gekregen.

Query naar je hand zetten

Bovenstaand fictief voorbeeld is een stevige vereenvoudiging van de feiten die slechts één nichevoorbeeld van een SQL-injectie-aanval illustreert. Het opzet is echter steevast hetzelfde. Bij SQL-injectie vindt een hacker een manier om input te koppelen aan een query. Hij schrijft die input zo dat de query een ander functie krijgt, op maat van wat de hacker wil. Zo kan de aanvaller logingegevens of andere gevoelige informatie uit een database stelen maar ook de database en de bijhorende applicatie saboteren, bijvoorbeeld door data te veranderen of te wissen.

Een goed uitgevoerde SQL-injectie kan duidelijk desastreuze gevolgen hebben. In sommige gevallen is het zelfs mogelijk voor de aanvaller om de database en het systeem zo te manipuleren dat hij of zij toegang krijgt tot het achterliggende OS. In dat geval is de SQL-kwetsbaarheid een vector voor een meer geavanceerde aanval.

Injectiebescherming

Bij aanvallers zijn SQL-kwetsbaarheden erg populair omdat ze eenvoudig zijn. Dergelijke aanvallen voorkomen is helaas minder eenvoudig. Ons voorbeeld zal je vandaag niet meteen tegenkomen in de realiteit, maar varianten wel. In de regel is het een goed idee om de front-end van de webapp niet rechtstreeks te laten praten met de back-end. Die back-end heeft weliswaar input nodig van gebruikers, maar ontwikkelaars kunnen een buffer inbouwen tussen die input en de query’s die uiteindelijk zullen draaien. Zo kan een toepassing invoer weigeren waarin () verwerkt zit. Dat zou de injectie in bovenstaand scenario alvast onmogelijk maken.

Input opschonen is het belangrijkste wapen tegen SQL-injecties. Onafhankelijk van de bron van de invoer moeten ontwikkelaars een controlelaag inbouwen. Gaat het om een toepassing waar input van de front-end komt? Dan is het eenvoudig om bepaalde tekens te verbieden, een maximale lengte te bepalen of een specifieke vorm op te leggen (x@y.z voor een mailadres bijvoorbeeld). Ook invoer afkomstig van API’s verdient geen vol vertrouwen. Zodra een aanvaller een manier vindt om eigen SQL-code te injecteren in de back-end, is het hek immers van de dam.

lees ook

Sunburst-hack kost SolarWinds 3,5 miljoen dollar

Verder is het een goed idee voor ontwikkelaars om eventuele foutmeldingen intern te houden. Wanneer bepaalde invoer een foutmelding genereert, zou de gebruiker een generisch scherm moeten zien. De SQL-serverfout zelf is enkel voor beheerders geschikt, aangezien die een indicatie kan geven van mogelijk misbruik.

Geen pasklare oplossing

In de praktijk blijft het moeilijk om SQL-injecties te voorkomen. De alomtegenwoordigheid van legacy-software draagt daar een stukje verantwoordelijkheid. SQL-injecties stonden vroeger niet altijd even hoog op de prioriteitenlijst van mogelijke bedreigingen. Moderne infrastructuur en toepassingen worden alsmaar complexer, wat op zijn beurt meer ruimte creëert voor injectiemogelijkheden die over het hoofd worden gezien.

Bovendien is er geen éénduidige oplossing die SQL-injectie onmogelijk maakt. Er bestaan immers heel veel varianten en technieken om SQL-code te manipuleren. Zodra een aanvaller ergens input kan aanpassen die uiteindelijk in een query terecht komt, bestaat er een risico. De laatste SQL-injectiekwetsbaarheid hebben we daarom nog lang niet gezien.

nieuwsbrief

Abonneer je gratis op ITdaily !

  • This field is for validation purposes and should be left unchanged.