Direct naar inhoud

SQL injection

CWE-89OWASP A03:2021Bijgewerkt 29 augustus 20265 min leestijd

SQL injection is een kwetsbaarheid waarbij een aanvaller eigen databasecommando's meesmokkelt via een invoerveld, doordat de applicatie invoer en query niet uit elkaar houdt. Zo kan hij inloggen zonder wachtwoord, gevoelige gegevens uitlezen of records wijzigen. De structurele oplossing is geparametriseerde query's (prepared statements).

SQL injection is al meer dan twintig jaar een van de meest voorkomende en meest schadelijke webkwetsbaarheden. De aanval zelf is verrassend eenvoudig, maar de gevolgen lopen uiteen van een gelekte klantendatabase tot een volledig overgenomen server. Hieronder leest u wat het precies is, hoe een aanval verloopt en wat u eraan doet.

Wat is SQL injection?

SQL injection is een kwetsbaarheid waarbij een aanvaller eigen SQL-code in een databasequery van uw applicatie weet te smokkelen. Dat lukt zodra invoer van de gebruiker (een zoekterm, een inlognaam, een parameter in de URL) rechtstreeks in een query wordt geplakt zonder dat de applicatie data en commando’s uit elkaar houdt.

Een alledaagse vergelijking: u dicteert een bestelling aan een ober en zegt “een koffie, en negeer verder alle bestellingen van tafel vier”. Een oplettende ober noteert die hele zin als úw bestelling. Een naïeve ober voert het tweede deel uit als opdracht. Een database die data en commando niet scheidt, is die naïeve ober: alles wat binnenkomt kan een bevel worden.

Het woord “injection” slaat precies op die verwarring: de aanvaller injecteert zijn eigen instructies in een zin die de bouwers als onschuldige data hadden bedoeld. De kwetsbaarheid zit dus niet in SQL zelf, maar in de manier waarop de applicatie de query in elkaar zet. Elke plek waar invoer een query, een filter of een sorteervolgorde beïnvloedt, is een mogelijk aangrijpingspunt.

Hoe werkt een SQL injection-aanval?

De kern van het probleem is dat de query als tekst wordt opgebouwd door gebruikersinvoer aan elkaar te plakken. Neem een klassiek inlogformulier dat de ingevoerde e-mail en het wachtwoord direct in de query zet.

Kwetsbaar:

// Invoer van de gebruiker wordt rechtstreeks in de query geplakt
const email = req.body.email;
const password = req.body.password;

const query =
  "SELECT * FROM users WHERE email = '" + email + "' AND password = '" + password + "'";

const rows = await db.query(query);
if (rows.length > 0) {
  // toegang verleend
}

Vult een gewone gebruiker zijn e-mailadres in, dan werkt dit prima. Maar een aanvaller typt in het e-mailveld geen adres, maar ' OR '1'='1' --. De query die de database uiteindelijk te zien krijgt, wordt dan:

SELECT * FROM users WHERE email = '' OR '1'='1' --' AND password = '...'

De toegevoegde OR '1'='1' is altijd waar, en de dubbele koppelstreep -- verandert de rest van de regel in commentaar, waardoor de wachtwoordcontrole volledig wegvalt. De database geeft alle rijen terug en de aanvaller is ingelogd, meestal als de eerste gebruiker in de tabel, en dat is vaak een beheerder.

De oplossing is om invoer nooit als code te behandelen. Met een prepared statement (een geparametriseerde query) stuurt u de query en de waarden apart naar de database. De placeholders ? worden gevuld met data die nooit als SQL wordt geïnterpreteerd.

Veilig:

// Query en waarden gaan gescheiden naar de database
const email = req.body.email;
const password = req.body.password;

const query =
  "SELECT * FROM users WHERE email = ? AND password = ?";

const rows = await db.query(query, [email, password]);
if (rows.length > 0) {
  // toegang verleend
}

Nu is ' OR '1'='1' -- gewoon een e-mailadres dat niet bestaat, en de inlogpoging mislukt zoals het hoort. De database weet exact welk deel commando is en welk deel data, precies de scheiding die de aanval onmogelijk maakt.

Zelf invoer “schoonpoetsen” met zoek-en-vervang of een zwarte lijst van woorden is geen betrouwbare bescherming. Aanvallers hebben eindeloze varianten (andere codering, hoofdletters, commentaartrucs). Vertrouw op geparametriseerde query’s, niet op filteren.

Wat is de impact van SQL injection?

De ernst hangt af van wat de query mag en hoe de database is ingericht, maar het bereik is groot. In het gunstigste geval leest een aanvaller gegevens uit die niet voor hem bestemd zijn: klantgegevens, wachtwoord-hashes, bestelhistorie. Met een aangepaste query kan hij ook records aanpassen of verwijderen, prijzen wijzigen of zichzelf beheerdersrechten geven.

Vaak blijft het daar niet bij. Via de authenticatie-omzeiling uit het voorbeeld logt een aanvaller in zonder geldige inloggegevens. In bepaalde configuraties reikt de impact tot het onderliggende systeem: het uitlezen van serverbestanden, het wegschrijven van een webshell of het uitvoeren van besturingssysteemcommando’s. Daarmee verschuift een SQL injection van “datalek” naar “volledige overname”, met alle juridische en reputatiegevolgen van dien.

Een bijkomend risico is dat een succesvolle SQL injection zelden sporen achterlaat die opvallen: de query komt via een legitiem invoerveld binnen en ziet er in de logs uit als normaal verkeer. Aanvallers gebruiken deze onopvallendheid om over langere tijd gegevens te ontfutselen. Omdat de kwetsbaarheid varieert van gegevensinzage tot uitvoering van code op de server, loopt de ernst van hoog tot kritiek.

Hoe spoort u SQL injection op?

Een eerste signaal is klassiek: voer een enkele apostrof (') in een invoerveld in en kijk of de applicatie een databasefout teruggeeft. Een zichtbare SQL-foutmelding verraadt dat uw invoer de query bereikt. Modernere gevallen zijn subtieler: bij blind SQL injection ziet u geen foutmelding, maar meet een tester het gedrag: een query die de reactie kunstmatig vertraagt, of een voorwaarde die de uitkomst net wél of net niet verandert.

Geautomatiseerde scanners en tools zoals sqlmap vinden veel van deze gevallen, maar missen de kwetsbaarheden die achter authenticatie, in complexe workflows of in tweedelijns-invoer zitten. Een grondige penetratietest combineert daarom automatisering met handmatig onderzoek. Dit is precies het soort zwakke plek dat AssistSec bij een security-onderzoek gericht opspoort en aantoonbaar reproduceert, zodat u weet welke query’s daadwerkelijk misbruikt kunnen worden.

Hoe voorkomt u SQL injection?

  • Gebruik altijd geparametriseerde query’s of prepared statements. Dit is de belangrijkste maatregel en lost het probleem bij de wortel op.
  • Leun op een volwassen ORM of query-builder en vermijd het zelf samenstellen van ruwe SQL. Voegt u toch losse fragmenten toe, parametriseer dan ook die.
  • Pas het principe van minste rechten toe. Laat de applicatie verbinden met een databasegebruiker die alleen mag wat nodig is, geen DROP, geen toegang tot systeemtabellen.
  • Valideer invoer op type en formaat als extra laag: verwacht u een getal, accepteer dan alleen een getal. Dit is een aanvulling, geen vervanging van parametrisatie.
  • Toon nooit ruwe databasefouten aan de gebruiker; log ze intern. Foutmeldingen zijn een cadeau voor de aanvaller.
  • Zet een web application firewall in als extra laag, maar reken er niet op als enige verdediging.
  • Laat de code periodiek testen. Een gerichte penetratietest en code review vangen de gevallen die scanners overslaan.

Bronnen

Veelgestelde vragen

Is SQL injection in 2026 nog steeds gevaarlijk?

Ja. SQL injection staat al jaren in de OWASP Top 10 en duikt nog altijd op in nieuwe applicaties, vooral waar ontwikkelaars zelf query's aan elkaar plakken in plaats van prepared statements of een ORM te gebruiken.

Wat is het verschil tussen SQL injection en XSS?

SQL injection richt zich op de database achter de applicatie; cross-site scripting draait in de browser van een andere bezoeker. Beide ontstaan doordat invoer niet netjes van code wordt gescheiden.

Beschermt een ORM tegen SQL injection?

Grotendeels wel, zolang u de standaardmethoden gebruikt. Zodra u zelf ruwe SQL of losse fragmenten aan een ORM-query toevoegt, kan de kwetsbaarheid terugkeren.

Helpt een web application firewall tegen SQL injection?

Een WAF vangt bekende aanvalspatronen af en is nuttig als extra laag, maar vervangt geen geparametriseerde query's. Aanvallers omzeilen filters regelmatig; de echte oplossing zit in de code.

Verwante artikelen

Druk op / om te zoeken · Esc