WordPress security hardening: geavanceerde beveiliging
Laatst bijgewerkt: 31 December 2025
Basis WordPress beveiliging is een goede start, maar serieuze sites vereisen geavanceerde maatregelen. Dit artikel behandelt security hardening op server-, applicatie- en codeniveau.
Waarom Extra Hardening?
WordPress is het meest aangevallen CMS ter wereld. Niet omdat het onveilig is, maar omdat het zo populair is. Een standaard beveiligde site stopt 90% van de aanvallen. Hardening stopt de overige 10%.
Dreigingslandschap
- Brute force: Geautomatiseerd wachtwoorden raden
- Plugin-kwetsbaarheden: Verouderde of slechte code
- SQL injection: Database-manipulatie via invoervelden
- XSS: Kwaadaardige scripts injecteren
- File inclusion: Ongeautoriseerde bestanden uitvoeren
Server-Level Hardening
PHP Configuratie
Pas php.ini aan voor betere beveiliging:
; Verberg PHP-versie
expose_php = Off
; Beperk bestandsoperaties
open_basedir = /home/user/public_html:/tmp
; Schakel gevaarlijke functies uit
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
; Beperk includes tot eigen directory
allow_url_include = Off
allow_url_fopen = Off
; Session beveiliging
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
Apache/Nginx Hardening
.htaccess (Apache):
# Blokkeer directe toegang tot gevoelige bestanden
<FilesMatch "^(wp-config\.php|readme\.html|license\.txt)">
Order allow,deny
Deny from all
</FilesMatch>
# Voorkom directory listing
Options -Indexes
# Blokkeer PHP-uitvoering in uploads
<Directory "/var/www/html/wp-content/uploads">
<FilesMatch "\.php$">
Order allow,deny
Deny from all
</FilesMatch>
</Directory>
# Bescherm .htaccess zelf
<Files .htaccess>
Order allow,deny
Deny from all
</Files>
# Security headers
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Nginx equivalent:
# Blokkeer gevoelige bestanden
location ~* /(wp-config\.php|readme\.html|license\.txt) {
deny all;
}
# Geen PHP in uploads
location ~* /wp-content/uploads/.*\.php$ {
deny all;
}
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
Database Beveiliging
Gebruik een unieke database prefix (niet wp_):
$table_prefix = 'hr7x_';
Beperk database-gebruikersrechten:
-- Alleen noodzakelijke rechten
GRANT SELECT, INSERT, UPDATE, DELETE ON database.* TO 'wpuser'@'localhost';
-- Geen DROP, ALTER, GRANT rechten
wp-config.php Hardening
// Forceer SSL voor admin
define('FORCE_SSL_ADMIN', true);
// Blokkeer bestandswijzigingen via admin
define('DISALLOW_FILE_EDIT', true);
// Blokkeer plugin/thema installatie via admin
define('DISALLOW_FILE_MODS', true);
// Unieke salts (genereer op api.wordpress.org/secret-key)
define('AUTH_KEY', 'unieke-waarde-hier');
define('SECURE_AUTH_KEY', 'unieke-waarde-hier');
define('LOGGED_IN_KEY', 'unieke-waarde-hier');
define('NONCE_KEY', 'unieke-waarde-hier');
define('AUTH_SALT', 'unieke-waarde-hier');
define('SECURE_AUTH_SALT', 'unieke-waarde-hier');
define('LOGGED_IN_SALT', 'unieke-waarde-hier');
define('NONCE_SALT', 'unieke-waarde-hier');
// Beperk revisies
define('WP_POST_REVISIONS', 5);
// Automatische updates voor security
define('WP_AUTO_UPDATE_CORE', 'minor');
Bestandspermissies
Correcte permissies zijn cruciaal:
# Directories: 755
find /var/www/html -type d -exec chmod 755 {} \;
# Bestanden: 644
find /var/www/html -type f -exec chmod 644 {} \;
# wp-config.php extra beveiligd
chmod 600 wp-config.php
# Uploads directory mag schrijfbaar zijn
chmod 755 wp-content/uploads
Login Beveiliging
Verplaats wp-admin
// In wp-config.php
define('WP_ADMIN_DIR', 'geheim-admin-pad');
// In functions.php
add_filter('site_url', function($url, $path, $scheme) {
if ($path === 'wp-login.php' && !is_admin()) {
return str_replace('wp-login.php', WP_ADMIN_DIR, $url);
}
return $url;
}, 10, 3);
Two-Factor Authentication
Verplicht 2FA voor alle admins. Gebruik plugins zoals:
- Google Authenticator
- Duo Security
- Hardware keys (YubiKey)
Login Limiting
// Beperk inlogpogingen
function limit_login_attempts($user, $username, $password) {
$ip = $_SERVER['REMOTE_ADDR'];
$transient = 'login_attempts_' . md5($ip);
$attempts = get_transient($transient) ?: 0;
if ($attempts >= 5) {
return new WP_Error('too_many_attempts',
'Te veel inlogpogingen. Probeer over 15 minuten opnieuw.');
}
return $user;
}
add_filter('authenticate', 'limit_login_attempts', 30, 3);
function track_failed_login($username) {
$ip = $_SERVER['REMOTE_ADDR'];
$transient = 'login_attempts_' . md5($ip);
$attempts = get_transient($transient) ?: 0;
set_transient($transient, $attempts + 1, 15 * MINUTE_IN_SECONDS);
}
[add_action](/kennisbank/wordpress-hooks-uitleg)('wp_login_failed', 'track_failed_login');
Content Security Policy
CSP voorkomt XSS-aanvallen:
add_action('send_headers', function() {
header("Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' https://trusted-cdn.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self';
frame-ancestors 'self';
");
});
XML-RPC Uitschakelen
XML-RPC is een veelgebruikte aanvalsvector:
// Volledig uitschakelen
add_filter('xmlrpc_enabled', '__return_false');
// Of via .htaccess
<Files xmlrpc.php>
Order deny,allow
Deny from all
</Files>
REST API Beveiligen
Beperk de REST API voor niet-ingelogde gebruikers:
add_filter('rest_authentication_errors', function($result) {
if (!is_user_logged_in()) {
// Sta publieke endpoints toe
$public_routes = ['/wp/v2/posts', '/wp/v2/pages'];
$route = $_SERVER['REQUEST_URI'];
foreach ($public_routes as $public) {
if (strpos($route, $public) !== false) {
return $result;
}
}
return new WP_Error('rest_forbidden',
'Authenticatie vereist', ['status' => 401]);
}
return $result;
});
Monitoring en Logging
Activiteitenlog
function log_security_event($message, $level = 'info') {
$log_file = WP_CONTENT_DIR . '/security.log';
$timestamp = date('Y-m-d H:i:s');
$ip = $_SERVER['REMOTE_ADDR'];
$user = wp_get_current_user();
$username = $user->ID ? $user->user_login : 'anonymous';
$entry = "[{$timestamp}] [{$level}] [{$ip}] [{$username}] {$message}\n";
file_put_contents($log_file, $entry, FILE_APPEND | LOCK_EX);
}
// Log belangrijke acties
add_action('wp_login', function($username) {
log_security_event("Successful login: {$username}");
});
add_action('wp_login_failed', function($username) {
log_security_event("Failed login attempt: {$username}", 'warning');
});
File Integrity Monitoring
Controleer regelmatig of kernbestanden gewijzigd zijn:
# Genereer checksums
find /var/www/html/wp-includes -type f -name "*.php" \
-exec md5sum {} \; > /root/wp-checksums.txt
# Vergelijk later
md5sum -c /root/wp-checksums.txt 2>&1 | grep FAILED
Security Headers Testen
Test je configuratie op:
- securityheaders.com
- observatory.mozilla.org
- ssllabs.com/ssltest
Incident Response Plan
Bereid je voor op het ergste:
- Detectie: Monitoring alerts configureren
- Isolatie: Site offline halen indien nodig
- Analyse: Logs onderzoeken, besmetting identificeren
- Herstel: Schone backup terugzetten
- Preventie: Kwetsbaarheid dichten, hardening verbeteren
Meer informatie: WordPress.org documentatie
Veelgestelde vragen
Hoe lang duurt het om dit te implementeren?
De implementatietijd varieert per situatie. Voor eenvoudige configuraties is dit binnen een uur geregeld, complexere setups kunnen enkele uren tot een dag duren.
Wat zijn de kosten?
De kosten zijn afhankelijk van je hosting provider en pakket. Veel basisfuncties zijn gratis inbegrepen, voor geavanceerde functies kunnen extra kosten gelden.
Heb ik technische kennis nodig?
Voor de basis heb je weinig technische kennis nodig. De meeste hosting providers bieden uitgebreide documentatie en support om je te helpen.
Was dit artikel nuttig?
Vergelijk direct hosting pakketten om de beste keuze voor jouw situatie te maken.
Gerelateerde artikelen
Wat is webhosting? Uitleg voor beginners
Ontdek wat webhosting is en hoe het werkt. Complete uitleg over servers, domeinen en verschillende hosting types voor beginners.
Wat is VPS hosting?
VPS hosting uitgelegd: wat is een virtual private server, voor wie is het geschikt en wat zijn de voordelen ten opzichte van shared hosting?
Wat is een SSL-certificaat?
Alles over SSL-certificaten: wat is SSL, waarom heb je het nodig en hoe herken je een beveiligde website? Essentieel voor elke website.
Wat is uptime bij webhosting?
Wat betekent uptime bij webhosting? Leer over uptime percentages, SLA garanties en waarom 99.9% uptime belangrijk is voor je website.
Hoeveel opslag heb ik nodig voor mijn website?
Ontdek hoeveel schijfruimte je echt nodig hebt voor je website. Praktische gids met voorbeelden per websitetype.