SQL injection voorkomen in WordPress: maatregelen die echt werken

SQL injection voorkomen in WordPress: hoe de aanval vandaag werkt, welke code-patronen veilig zijn en welke plugins en WAF-regels het verschil maken.

· 26 juni, 2026 · 8 min lezen
In het kort
  • SQL injection voorkomen WordPress draait om drie dingen: veilige queries, invoer controleren en updaten.
  • Gebruik altijd $wpdb->prepare() voor queries met variabelen; dat is de belangrijkste bescherming.
  • Sanitize invoer op de juiste laag en escape je output; vertrouw geen enkele gebruikersinvoer.
  • Verouderde plugins zijn de grootste bron; houd alles bij en zet een WAF ervoor als extra laag.
In dit artikel

SQL injection voorkomen WordPress begint bij één inzicht: de aanval komt vrijwel altijd binnen via verouderde plugins en slecht geschreven custom code. SQL injection staat al meer dan tien jaar in de OWASP Top 10 en het is er nog steeds. Volgens OWASP hoort injection bij de meest voorkomende kwetsbaarheden op het web. Op WordPress komt het vooral binnen via verouderde plugins en slecht geschreven custom code.

Dit artikel laat zien hoe je SQL injection voorkomt in WordPress. Niet alleen de algemene tips, maar concreet: welk patroon je in PHP gebruikt, welke functies sanitiseren, welke plugins het fout doen en welke WAF-regels het opvangen. Code-voorbeelden inbegrepen.

Ik ben technisch implementeerder, geen SEO-strateeg. Wat hieronder staat, gebruik ik dagelijks bij hardening na een incident en bij onderhoud op bestaande sites.

Veilige WordPress query met wpdb prepare als bescherming tegen SQL injection in een code-editor

Hoe SQL injection vandaag op WordPress werkt

Een SQL injection-aanval slaat code binnen via een invoerveld of URL-parameter. Die code wordt door de database uitgevoerd als ware het een gewone query. Het klassieke voorbeeld is een formulierveld met ' OR '1'='1 dat de hele gebruikerstabel teruggeeft.

In WordPress zelf is de core relatief goed beschermd. De $wpdb-klasse biedt veilige functies voor database-queries. Maar de meeste sites draaien tientallen plugins en thema’s. Daar zit de zwakke plek.

Wat ik in de praktijk zie als hoofdoorzaken:

  • Verouderde plugins die nog werken met oude database-functies
  • Custom code in een thema dat door een vorige bouwer is achtergelaten
  • Formulieren of zoekfunctionaliteit die direct queries opbouwt
  • Imports of API-koppelingen die externe data zonder controle doorzetten

Het patroon is bijna altijd hetzelfde: ergens komt input binnen die zonder bewerking in een query belandt. Het doel van hardening is om dat patroon overal te doorbreken.

Het $wpdb->prepare()-patroon

De basis voor veilige queries in WordPress heet prepare(). Het is een functie van de $wpdb-klasse die placeholders gebruikt in plaats van directe stringconcatenatie. Officiële documentatie staat in de WordPress developer reference.

Een onveilige query ziet er zo uit:

php

$user_id = $_GET['user_id'];
$result = $wpdb->get_row("SELECT * FROM wp_users WHERE ID = $user_id");

Dit is direct kwetsbaar. Iemand kan 1; DROP TABLE wp_users meesturen en de tabel verdwijnt.

De veilige variant gebruikt prepare():

php

$user_id = absint($_GET['user_id']);
$result = $wpdb->get_row(
    $wpdb->prepare(
        "SELECT * FROM wp_users WHERE ID = %d",
        $user_id
    )
);

Twee dingen gebeuren hier. Eerst dwingt absint() de input naar een positief geheel getal. Daarna zorgt %d ervoor dat de waarde als integer in de query terechtkomt, escaped en al.

De placeholders zijn:

  • %d voor integers
  • %f voor floats
  • %s voor strings (automatisch quoted en escaped)
  • %i voor identifiers zoals tabel- en kolomnamen (sinds WordPress 6.2)

Schrijf je een query met $wpdb? Dan moet er altijd een prepare() omheen, ook als de input “van een veilige bron” lijkt. Vertrouw geen input, ook niet je eigen.

SQL injection simulatie

Zie het verschil: kwetsbare vs veilige query

Kies een invoer en voer hem “uit”. Links een query met concatenatie, rechts dezelfde met $wpdb->prepare(). Dit is een veilige simulatie, er draait geen echte database.

Kwetsbaar (concatenatie)

Kwetsbaar
$sql = "SELECT * FROM wp_users WHERE user_login = 'Jan'";

Veilig (prepare)

Veilig
$sql = $wpdb->prepare( "SELECT * FROM wp_users WHERE user_login = %s", "Jan" );

De veilige query behandelt invoer altijd als waarde, nooit als code. Dat is precies wat $wpdb->prepare() doet.

Interactieve simulatie, zet JavaScript aan.

$sql = "SELECT * FROM wp_users WHERE user_login = '" . $_GET['u'] . "'"; $sql = $wpdb->prepare( "SELECT * FROM wp_users WHERE user_login = %s", $_GET['u'] );

De veilige query behandelt invoer altijd als waarde, nooit als code. Dat is precies wat $wpdb->prepare() doet.

Input sanitization op de juiste laag

Naast prepare() is sanitization van input een tweede verdedigingslaag. WordPress heeft een lijst sanitization-functies die je per veldtype toepast.

De meest gebruikte:

  • sanitize_text_field() voor losse tekstvelden
  • sanitize_email() voor e-mailadressen
  • sanitize_key() voor slugs en interne keys
  • absint() voor positieve integers
  • intval() voor algemene integers
  • esc_url_raw() voor URL’s die in de database komen
  • wp_kses_post() voor HTML-content waar wel tags in mogen

Belangrijk: sanitize op input, escape op output. Dat zijn twee verschillende stappen. Sanitization gaat over wat je opslaat. Escaping (esc_html, esc_attr, esc_url) gaat over hoe je het laat zien.

Voor formulieren die je zelf bouwt, ziet het er ongeveer zo uit:

php

$email = sanitize_email( $_POST['email'] ?? '' );
$name  = sanitize_text_field( $_POST['name'] ?? '' );

if ( ! is_email( $email ) ) {
    wp_die( 'Ongeldig e-mailadres' );
}

Pas hierna komt het opslaan via $wpdb->insert(), dat zelf al placeholders gebruikt.

Verouderde WordPress plug-ins met vulnerability-waarschuwingen als grootste SQL injection risico

Plugins die het fout doen

In mijn ervaring zijn drie soorten plugins de meest voorkomende bron van SQL injection-kwetsbaarheden op WordPress.

Oude formulier-plugins. Vooral plugins die jaren niet zijn bijgewerkt. Ze bouwen queries vaak met stringconcatenatie. Bij een audit op een gehackte site is dit doorgaans de eerste plek waar ik kijk.

Custom plugins van vorige bouwers. Een ontwikkelaar bouwt een snelle koppeling met een externe API. Werkt prima, gaat live, niemand kijkt er meer naar. Twee jaar later zit er een lek in. Custom plugins krijgen geen automatische security-fixes.

Plugins met “premium” patches via nulled-sites. Gepirateerde versies van betaalde plugins. Die zijn vaak getampered met. Lypii-beleid is duidelijk: nooit gebruiken, nooit aanraden. Wie een nulled-plugin draait, draait een blackbox.

Hoe vind je verdachte plugins? Een aantal stappen:

  1. Controleer welke plugins meer dan zes maanden geen update kregen
  2. Check elke plugin tegen de Patchstack-database op bekende kwetsbaarheden
  3. Verwijder plugins die je niet actief gebruikt
  4. Bij twijfel: deactiveer en kijk of de site nog werkt

Op een lopend onderhoudscontract loopt dit elke maand mee. Dat is de reden waarom een WordPress onderhoudscontract goedkoper uitkomt dan reageren na een hack.

.htaccess-regels die helpen

Apache- en LiteSpeed-servers met een .htaccess-bestand kunnen een aantal generieke injection-pogingen al op de webserver tegenhouden. Dit vervangt geen veilige code, het is een extra filter aan de poort.

Een voorbeeld van regels die ik gebruik:

apache

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{QUERY_STRING} (union|select|insert|drop|update|md5|benchmark) [NC,OR]
    RewriteCond %{QUERY_STRING} (concat|sleep|delete|truncate) [NC,OR]
    RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC]
    RewriteRule .* - [F,L]
</IfModule>

Dit blokkeert URL’s met verdachte SQL-keywords in de query string. Pas op: te agressieve regels kunnen legitieme functionaliteit breken. Test dit altijd op staging voor het live gaat. Voor Nginx draait de logica via de server-config, niet via .htaccess.

Voor wp-admin zelf kan je een extra IP-restrictie toevoegen, of basic auth voor wp-login.php. Niet specifiek voor SQL injection, wel een algemene hardening-stap die scriptkiddies stopt.

WAF: Wordfence, Sucuri en Cloudflare

Een Web Application Firewall vangt veel injection-pogingen op voordat ze de site bereiken. Drie opties die ik in de praktijk inzet.

Wordfence. Plugin-based WAF die binnen WordPress draait. Werkt prima voor kleinere sites. De gratis versie heeft een vertraging op nieuwe signatures, premium krijgt ze direct. Punt van aandacht: Wordfence draait pas nadat WordPress is opgestart, dus zware botaanvallen kosten alsnog server-resources.

Sucuri. Cloud-based WAF die voor de site staat. Het verkeer loopt eerst via Sucuri, dan pas naar je server. Beter tegen DDoS en zware aanvallen, duurder per maand. Goed voor webshops en sites met veel verkeer.

Cloudflare. Combinatie van CDN en WAF. De gratis versie heeft beperkte WAF-regels, de Pro-versie en hoger biedt OWASP-rule sets. Voor MKB-sites vaak een goede balans tussen prijs en bescherming. Documentatie staat in de Cloudflare WAF-docs.

Geen van deze WAF’s vervangt veilige code. Ze vangen het meest voorkomende verkeer op, maar een doelgerichte aanval op een specifieke plugin-kwetsbaarheid komt soms toch door. Defense in depth: meerdere lagen die elkaar opvangen.

WAF-regels in .htaccess voor extra bescherming tegen SQL injection patterns op een WordPress site

SQL injection voorkomen WordPress: praktische volgorde

Werkt het allemaal samen? Ja, maar niet alles tegelijk. Een typische hardening-volgorde op een bestaande site:

  1. Eerst audit van plugins en thema’s, verouderde en ongebruikte exemplaren verwijderen
  2. Updates van core, plugins en thema’s op staging testen, daarna doorvoeren
  3. Custom code in het thema en eventuele custom plugins doorlopen op $wpdb-gebruik
  4. WAF activeren of upgraden (Wordfence, Sucuri of Cloudflare)
  5. .htaccess– of Nginx-regels toevoegen voor generieke query-string filtering
  6. Logs nakijken op verdachte patronen van de afgelopen 30 dagen
  7. Back-up- en restore-test draaien

Voor een gemiddelde mkb-site kost dit één tot drie uur, afhankelijk van de hoeveelheid custom code. Voor een gehackte WordPress-site herstellen is dit een vast onderdeel van de cleanup. Geen herstel zonder hardening, anders ben je er volgende maand weer.

Wat ik niet doe

Eerlijk benoemen wat er buiten scope valt. Juridisch advies bij een datalek hoort bij een privacy-advocaat, niet bij een webmaster. Pen-tests op enterprise-niveau zijn werk voor gespecialiseerde security-bureaus.

Wat ik wel doe: praktische hardening voor MKB-sites die normaal in productie draaien. WordPress, WooCommerce, en ook Joomla, Drupal of Laravel als dat in je stack zit. De principes (prepared statements, sanitization, WAF) gelden buiten WordPress net zo goed.

Geen 24/7-support. ’s Nachts ben ik niet beschikbaar, behalve bij afgesproken spoed. Spoedwerk reken ik tegen €105 per uur. Standaard uurtarief is €70. Voor lopend onderhoud zijn er twee abonnementen: Onderhoud Basis op €58 per maand en Onderhoud Plus op €175 per maand.

Heb je een concrete vraag of een vermoeden van een kwetsbaarheid? Stuur de URL en kort wat je ziet. Ik reageer binnen 4 uur op werkdagen. Meer artikelen staan in de categorie website beveiliging.

Serhii Lypii
Gratis meedenken

Een security-check aanvragen

Stuur me je URL en, als je het weet, om welke plugin of welk formulier het gaat. Ik kijk naar de code en de logs en mail terug met wat er nodig is. Geen verkooppraat, wel een eerlijk beeld.

Vraag een security-check aan
Vond je dit nuttig? Deel het:
FAQ

Veelgestelde vragen

Is WordPress core veilig tegen SQL injection?
WordPress core is goed beschermd zolang je $wpdb->prepare() gebruikt en de officiële API's volgt. Kwetsbaarheden zitten bijna altijd in plugins, thema's of custom code. Updates blijven nodig, ook voor core.
Is een WAF genoeg, of moet ik ook de code aanpassen?
Een WAF is een extra laag, geen vervanging voor veilige code. Een gerichte aanval op een specifieke plugin komt soms door de WAF heen. Veilige code is de basis, de WAF vangt de rest op.
Wat doe ik met een plugin die niet meer geüpdatet wordt?
Eerst kijken of er een alternatief is dat wel onderhouden wordt. Lukt dat niet, dan staat de plugin op de zwarte lijst. Een verouderde plugin is op den duur altijd een lek, ook zonder dat je het merkt.
Hoe weet ik of mijn site is aangevallen?
Logs nakijken op ongebruikelijke URL's met SQL-keywords. Onverwachte gebruikersaccounts in de database. Bestanden in wp-content/uploads die er niet horen. Bij Wordfence of Sucuri staat een overzicht in het dashboard.
Mag ik nulled of gepirateerde plugins gebruiken als ze werken?
Nee. Gepirateerde plugins zijn een van de meest voorkomende redenen waarom klanten met geïnfecteerde sites bij mij komen. Ik gebruik en raad ze nooit aan.
Kan ik dit zelf doen of moet ik hulp inschakelen?
Voor de basis (updates, een WAF activeren, oude plugins opruimen) kan een handige beheerder veel zelf. Voor code-audit en het herschrijven van onveilige queries is wat developer-ervaring nodig. Bij twijfel: één uur intake levert vaak een duidelijke prioriteitenlijst op.
Serhii Lypii
Over de auteur

Serhii Lypii

Freelance webmaster · Terneuzen

Sinds 2012 werk ik met websites en leverde ik ruim 210 projecten op. Ik help mkb-ondernemers met onderhoud, snelheid, beveiliging en praktische automatisering. Nuchter, zonder hype.

Ik schreef dit artikel op en werkte het voor het laatst bij op .

Meer over Lypii
Even sparren over je site?

Loop je ergens tegenaan of twijfel je over je site? Ik denk graag mee — kies hieronder hoe je contact opneemt.

Reactie binnen 4 uur op werkdagen
Navigatie
Home Over mij Kennisbank
Contact
+31 6 39 56 93 03 serhii@lypii.nl WhatsApp
Stuur een bericht