Beveiliging afstemmen op WordPress
WordPress geeft je volledige controle over de headers en de opmaak van je pagina, dus vrijwel alles wat deze check meldt kun je zelf oplossen. Hieronder per soort bevinding waar de fix woont, met code die je kunt overnemen. WooCommerce is voor deze fixes gewoon WordPress: het is een plugin, dus de header-fix is de WordPress-fix.
Response-headers (HSTS, clickjacking, MIME-sniffing, referrer, permissions)
HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy en Permissions-Policy zet je op één plek voor je hele site. Drie routes, kies wat bij je past. In de serverconfig is het het robuustst, want dan gelden de headers ook voor bestanden die PHP niet aanraakt.
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
</IfModule>add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;add_action('send_headers', function () {
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
header('X-Frame-Options: SAMEORIGIN');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: strict-origin-when-cross-origin');
header('Permissions-Policy: camera=(), microphone=(), geolocation=()');
});Zonder bij de code te willen: een plugin
Kun of wil je niet bij de serverconfig of functions.php, dan zet een security-headers-plugin dezelfde headers via een instellingenscherm. Voorbeelden zijn Really Simple Security en de plugin HTTP Headers; er zijn er meer. Kies er een die actief onderhouden wordt. Dit is geen aanbeveling van een specifiek product, alleen van de aanpak.
De Content-Security-Policy
De CSP is de zwaarste en de lastigste op WordPress, want thema's en plugins voegen vaak inline scripts toe die een strikte policy blokkeert. Rol hem daarom in stappen uit:
- Zet de policy eerst in report-only (de Content-Security-Policy-Report-Only-header), dan breekt hij niets maar meldt hij wel wat hij zou blokkeren.
- Verzamel de meldingen met een tool als Sentry, Report URI of URIports, of lees ze in je browserconsole.
- Sta toe wat legitiem geblokkeerd wordt, tot er geen echte meldingen meer binnenkomen.
- Hernoem de header naar Content-Security-Policy om de policy af te dwingen.
# Watch the reports first, then switch the header name to
# Content-Security-Policy once nothing legitimate is blocked.
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"In de pagina (hash op een script, trackers na toestemming)
Een integrity-hash op een extern script hangt aan het script-tag, niet in een header. In WordPress voeg je die toe via een filter op de enqueue. En trackers die pas na toestemming mogen laden, regel je met een consent-plugin of een tag manager die op de toestemming wacht (bijvoorbeeld Complianz of CookieYes), niet door het script direct in te sluiten.
add_filter('script_loader_tag', function ($tag, $handle, $src) {
if ($handle !== 'the-external-handle') {
return $tag;
}
return str_replace(
'></script>',
' integrity="sha384-REPLACE_WITH_THE_REAL_HASH" crossorigin="anonymous"></script>',
$tag
);
}, 10, 3);De verbinding (HTTPS afdwingen)
Zet in Instellingen > Algemeen zowel het WordPress-adres als het site-adres op https, en stuur http door naar https op de server. Het certificaat zelf regelt je host of CDN, vaak met een gratis Let's Encrypt-certificaat en een schakelaar.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>DNS-records (SPF, DMARC, DNSSEC, IPv6)
Deze staan los van je site: het zijn records bij je domein. Je zet ze bij je DNS-provider of domeinregistrar, niet in je CMS of op je host. SPF en DMARC gaan over wie mail namens je domein mag sturen, DNSSEC ondertekent je DNS, en IPv6 is de enige waar de host eerst een AAAA-record en verbinding moet aanbieden voordat je die kunt zetten.