Sécurité

SQL-injectie voorkomen: de complete gids

SQL-injectie is een van de gevaarlijkste webkwetsbaarheden. Leer hoe u uw database beschermt met bewezen technieken.

18 mars 20263 min de lectureWarDek Team

Wat is SQL-injectie?

SQL-injectie (SQLi) is een aanvalstechniek waarbij kwaadaardige SQL-code wordt geïnjecteerd via gebruikersinvoer, waardoor een aanvaller ongeautoriseerde database-operaties kan uitvoeren. Ondanks dat het een van de oudste webkwetsbaarheden is (bekend sinds 1998), staat het nog steeds in de OWASP Top 10 en wordt het actief misbruikt.

De gevolgen zijn ernstig: volledige database-extractie, data-wijziging, authenticatie-bypass, en in sommige gevallen overname van de server.

Hoe SQL-injectie werkt

Het basisprincipe

Een kwetsbare applicatie bouwt SQL-queries op door gebruikersinvoer direct in de query-string te plakken:

-- Kwetsbare query (NOOIT doen)
SELECT * FROM users WHERE username = '" + userInput + "' AND passwd = '" + passInput + "'

Als een aanvaller als gebruikersnaam invoert: admin' --

Wordt de query:

SELECT * FROM users WHERE username = 'admin' --' AND passwd = ''

Het -- maakt de rest van de query tot commentaar. De aanvaller logt in als admin zonder wachtwoord.

Typen SQL-injectie

| Type | Methode | Detectie | |---|---|---| | In-band (Classic) | Resultaat direct zichtbaar in response | Makkelijk te detecteren | | Error-based | Database-foutmeldingen onthullen informatie | Makkelijk te detecteren | | Union-based | UNION SELECT om data uit andere tabellen te lezen | Makkelijk te detecteren | | Blind (Boolean) | Waar/onwaar vragen stellen via condities | Moeilijker te detecteren | | Time-based blind | Vertragingen in response meten | Moeilijk te detecteren | | Out-of-band | Data via alternatief kanaal exfiltreren (DNS, HTTP) | Zeer moeilijk te detecteren |

De oplossing: parameterized queries

De primaire en meest effectieve bescherming tegen SQL-injectie is het gebruik van parameterized queries (ook bekend als prepared statements). Hierbij wordt de SQL-structuur gescheiden van de data.

Node.js (PostgreSQL)

// VEILIG — parameterized query
const result = await pool.query(
  'SELECT * FROM users WHERE email = $1 AND status = $2',
  [email, 'active']
);
// ONVEILIG — string concatenatie (NOOIT doen)
const result = await pool.query(
  `SELECT * FROM users WHERE email = '${email}'`
);

ORM's (Prisma, Drizzle)

ORM's gebruiken standaard parameterized queries:

// Prisma — automatisch veilig
const user = await prisma.user.findUnique({
  where: { email: userInput },
});

Let op: raw queries in ORM's omzeilen deze bescherming:

// ONVEILIG — raw query met string interpolatie
const result = await prisma.$queryRawUnsafe(
  `SELECT * FROM users WHERE name = '${userInput}'`
);

// VEILIG — raw query met parameters
const result = await prisma.$queryRaw`
  SELECT * FROM users WHERE name = ${userInput}
`;

Python (SQLAlchemy)

# VEILIG — parameterized
result = session.execute(
    text("SELECT * FROM users WHERE email = :email"),
    {"email": user_input}
)

PHP (PDO)

// VEILIG — prepared statement
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);

Aanvullende beschermingslagen

Laag 2: Input validatie

Valideer invoer op type, lengte en formaat. Dit vangt een deel van de aanvallen op maar is geen vervanging voor parameterized queries.

const emailSchema = z.string().email().max(255);
const idSchema = z.number().int().positive();

Laag 3: Least privilege

Geef de database-gebruiker van uw applicatie alleen de rechten die nodig zijn:

| Recht | Nodig voor webapplicatie? | |---|---| | SELECT | Ja | | INSERT | Meestal ja | | UPDATE | Meestal ja | | DELETE | Beperkt (soft delete overwegen) | | DROP | Nee | | CREATE | Nee (migraties via apart account) | | GRANT | Nooit |

Laag 4: Stored procedures

Voor complexe queries kunt u stored procedures gebruiken, die server-side worden gecompileerd en minder vatbaar zijn voor injectie.

Laag 5: WAF (Web Application Firewall)

Een WAF kan bekende SQL-injectie patronen blokkeren, maar is een vangnet — niet een primaire verdediging.

Laag 6: Foutafhandeling

Toon nooit database-foutmeldingen aan gebruikers in productie:

// ONVEILIG
catch (error) {
  res.status(500).json({ error: error.message }); // Onthult database-structuur
}

// VEILIG
catch (error) {
  logger.error({ error: error.message }, 'Database query failed');
  res.status(500).json({ error: 'Er is een fout opgetreden' });
}

Veelgemaakte fouten

| Fout | Risico | |---|---| | String concatenatie voor queries | Directe SQL-injectie kwetsbaarheid | | Raw queries zonder parameters | Omzeilt ORM-bescherming | | Vertrouwen op client-side validatie | Aanvaller stuurt direct HTTP-requests | | Database-fouten tonen in productie | Informatielekkage over structuur | | Te brede database-rechten | Aanvaller kan DROP TABLE uitvoeren | | Alleen WAF als bescherming | WAF-bypass technieken zijn bekend | | Vergeten van LIKE-clausules | % en _ zijn wildcards die moeten worden geëscaped |

SQL-injectie in context: NIS2 en AVG

SQL-injectie raakt direct aan compliance:

Testen op SQL-injectie

Handmatige tests

Veelgebruikte testpatronen voor invoervelden:

Geautomatiseerd

Geautomatiseerde security scanners testen systematisch alle invoerpunten op SQL-injectie kwetsbaarheden, inclusief blinde varianten die handmatig moeilijk te detecteren zijn.

Conclusie

SQL-injectie is een volledig te voorkomen kwetsbaarheid. Gebruik altijd parameterized queries, valideer invoer, beperk database-rechten en toon geen technische foutmeldingen in productie. Er is geen reden om in 2026 nog kwetsbaar te zijn voor SQLi.

Scan uw website gratis met WarDek — OWASP, NIS2, AVG, AI Act compliance in één scan.

#SQL injectie#database#beveiliging#OWASP

Scannez votre site gratuitement

WarDek détecte les vulnérabilités mentionnées dans cet article en quelques secondes.

Retour à Sécurité