Før et angrep kommer rekognosering. Bots skanner etter lavthengende frukt: kjent WordPress-versjon, åpen xmlrpc.php, svake innloggingssider. Når HTML-en din sier «WordPress 6.4.2», matcher skanneren CVE-er mot den versjonen og går videre til exploit-fasen.
Å skjule versjonen stopper ikke en målrettet angriper. Det reduserer støy fra masse-skanning. Den reelle forsvarslinjen er HTTP-sikkerhetshodere, lukkede endepunkter og strenge filrettigheter. Denne guiden dekker begge lagene - først obscurity, deretter hardenings som faktisk blokkerer angrep i nettleseren.
Security through obscurity - hva det er og ikke er
Security through obscurity betyr å skjule systemdetaljer slik at opportunistiske angripere bruker mer tid eller hopper over deg. Kritikere har rett i at et system bør være sikkert selv om alt er kjent. I praksis er begge ting sanne: skjul det du kan, herde resten.
WordPress lekker versjon flere steder:
- meta-taggen
generatori HTML-head - RSS- og Atom-feeds
- query-strengen
?ver=på CSS og JS readme.htmloglicense.txti rotkatalogen- enkelte REST-responser og feilmeldinger
Offentlige sikkerhetspatcher lister berørte versjoner. Når boten ser 6.5.0, vet den hvilke kjente hull som fortsatt kan gjelde. Fjern den informasjonen, så faller du ut av de enkleste skriptene.
Fjern generator og versjons-query-strenger
Installer ikke en tung sikkerhetsplugin bare for dette. Legg kode i child-temaets functions.php eller en liten must-use plugin:
remove_action( 'wp_head', 'wp_generator' );
remove_action( 'rss2_head', 'the_generator' );
remove_action( 'commentsrss2_head', 'the_generator' );
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'rsd_link' );
add_filter( 'the_generator', '__return_empty_string' );
function wppoland_strip_asset_ver( $src ) {
if ( is_string( $src ) && str_contains( $src, 'ver=' ) ) {
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
add_filter( 'style_loader_src', 'wppoland_strip_asset_ver', 9999 );
add_filter( 'script_loader_src', 'wppoland_strip_asset_ver', 9999 );str_contains() krever PHP 8+. På eldre PHP: bruk strpos( $src, 'ver=' ) !== false.
Cache-busting: Hvis du fjerner ?ver=, må du ha en annen strategi for å invalidere browser-cache etter deploy. Bruk filhash i filnavn (app.a1b2c3.css) eller en egen query-parameter du kontrollerer i build-steget. Ikke stol på WordPress-versjonsnummeret for cache.
Blokker readme og license
<FilesMatch "^(readme\.html|license\.txt)$">
Require all denied
</FilesMatch>Nginx:
location ~* /(readme\.html|license\.txt)$ {
deny all;
}HTTP-sikkerhetshodere - den reelle låsen
Versjonsfjerning er å ta husnummeret av døra. Security headers er dødboltene. I 2026 forventer nettlesere disse headerne. Uten dem står du åpen for klikk-kapring, MIME-sniffing og mange XSS-varianter.
X-Frame-Options
Hindrer at siden lastes i en fremmed <iframe> (klikk-kapring).
<IfModule mod_headers.c>
Header always append X-Frame-Options SAMEORIGIN
</IfModule>add_header X-Frame-Options "SAMEORIGIN" always;SAMEORIGIN lar deg bygge inn egen side. DENY er strengere hvis du aldri trenger iframes.
X-Content-Type-Options
Header set X-Content-Type-Options nosniffSier til nettleseren: stol på Content-Type fra serveren. En opplastet «.jpg» med JS inne skal ikke kjøres som skript.
Strict-Transport-Security (HSTS)
Tvinger HTTPS etter første sikre besøk. Aktiver bare når sertifikatet er stabilt.
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"max-age=31536000 = ett år. includeSubDomains dekker underdomener. preload er valgfritt og krever at du faktisk er klar for HSTS Preload-listen. Feil HSTS kan låse deg ute av HTTP midlertidig - test HTTPS grundig først.
Content-Security-Policy (CSP)
CSP begrenser hvilke kilder som kan laste skript, stiler og bilder. Det er den kraftigste headeren, og den som oftest ødelegger et WordPress-site hvis den settes for strengt uten testing.
Start i report-only:
Header set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; report-uri /csp-report"Når rapportene er rene, bytt til Content-Security-Policy (uten Report-Only). WordPress og mange plugins trenger fortsatt 'unsafe-inline' for skript og stiler - planlegg en gradvis stramming, ikke en hard cut overnight.
Referrer-Policy og Permissions-Policy
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"Referrer-Policy begrenser hva som lekker i Referer-headeren ved eksterne klikk. Permissions-Policy skrur av API-er du ikke bruker.
Deaktiver XML-RPC når du ikke trenger det
xmlrpc.php brukes fortsatt av Jetpack, noen mobilapper og remote publishing. Hvis du ikke bruker noen av dem, er endepunktet en klassisk brute-force-vektor (spesielt multicall).
Apache:
<Files xmlrpc.php>
Require all denied
</Files>Nginx:
location = /xmlrpc.php {
deny all;
}Alternativt i PHP hvis du ikke kan endre serverkonfig:
add_filter( 'xmlrpc_enabled', '__return_false' );Serverblokk er sterkere - forespørselen når aldri PHP.
Filrettigheter og wp-config.php
Typiske verdier på delt hosting:
- Mapper:
755 - Filer:
644 wp-config.php:400eller440(kun lesbar for eier/gruppe)
Ikke sett 777 «fordi opplasting ikke fungerer» - fiks eierskap og PHP-brukeren i stedet. På managed host (Kinsta, WP Engine, Flywheel) følger du leverandørens modell; chmod-rådene over gjelder mest klassisk VPS og cPanel.
Innlogging: rate limit og 2FA
Versjonsskjul hjelper lite hvis wp-login.php står åpen for passordgjetting. Praktisk minimum:
- Begrens innloggingsforsøk (plugin eller WAF-regel).
- Aktiver 2FA for alle administratorer.
- Unngå generiske brukernavn som
admin. - Overvåk mislykkede forsøk i serverlogger eller security-plugin.
Å endre innloggings-URL er obscurity igjen - nyttig mot støy, ikke erstatning for 2FA.
Hvordan verifisere at hardenings sitter
Etter deploy:
- Vis kildekode - sjekk at
generatorer borte. - Inspiser Network - CSS/JS skal ikke ha
?ver=6.x(med mindre du bevisst beholder egen cache-buster). - Bruk securityheaders.com eller
curl -I https://ditt-domene.no/for å lese responsheaders. - Bekreft at
/xmlrpc.phpreturnerer 403/404. - Bekreft at
/readme.htmler blokkert.
I Chrome DevTools: Application → Headers, eller Response Headers på dokument-requesten.
Hva denne guiden ikke erstatter
Oppdateringer av kjerne, tema og plugins er fortsatt viktigere enn obscurity. En uoppdatert plugin med RCE vinner over alle headers. Backup, staging før store oppgraderinger, og minst mulig angrepsflate (færre plugins) er del av samme jobb.
For en strukturert gjennomgang av sårbarheter og oppdateringsgjeld: se WordPress-sikkerhetsrevisjon. Trenger du hjelp til hardenings på et produksjonsmiljø: kontakt.
Child-tema vs must-use plugin
Ikke lim hardeningskode direkte inn i et parent-tema du oppdaterer fra repo. Bruk child-temaets functions.php, eller bedre: en must-use plugin under wp-content/mu-plugins/. MU-plugins lastes alltid og overlever temabytte.
<?php
/**
* Plugin Name: WPPoland Hardening
* Description: Versjonsstripping og relaterte filtre. Headers settes i serverkonfig.
*/
require __DIR__ . '/wppoland-hardening/strip-version.php';Hold HTTP-headers i Nginx/Apache eller i hostens WAF (Cloudflare Transform Rules, for eksempel). PHP header() i send_headers fungerer, men forsvinner lettere ved caching-lag som stripper eller overskriver responsheaders.
Cloudflare og managed WordPress-hosting
På Cloudflare kan du sette mange av de samme headerne som Transform Rules uten å røre .htaccess. På Kinsta, WP Engine og lignende er xmlrpc.php ofte allerede begrenset - sjekk panelet før du dobbeltblokkerer. Fjern fortsatt generator i PHP; hosten gjør sjelden det for deg.
Når du bruker page cache (Nginx FastCGI, LiteSpeed, Cloudflare APO), verifiser headers på den cachede HTML-responsen, ikke bare på en innlogget forespørsel. En header som bare settes i PHP bak cache-miss hjelper ikke anonyme besøkende.
CSP og vanlige WordPress-konflikter
Google Analytics, GTM, cookie-banner, reCAPTCHA, Stripe og kart-embeds krever egne script-src / frame-src / connect-src-oppføringer. Start bredt i report-only, samle brudd i en uke, deretter stram. Unngå 'unsafe-eval' med mindre et konkret plugin krever det og du har akseptert risikoen.
Inline-skript i temaer (klassiske onclick og <script> i footer) tvinger ofte 'unsafe-inline'. Migrer til wp_enqueue_script med filer du hasher, så kan du senere bruke nonces eller hashes i CSP.
Logging etter hardenings
Etter at du har blokkert XML-RPC og strammet innlogging, forvent støy i access-loggene (403 på /xmlrpc.php). Det er normalt. Det som ikke er normalt: plutselige 500-feil på forsiden etter CSP, eller innloggede redaktører som mister admin-AJAX fordi admin-ajax.php ble fanget av en for streng WAF-regel. Test wp-admin, Gutenberg-lagring og WooCommerce checkout hvis det finnes på samme domene.
Oppsummering
- Fjern generator, feed-versjon og
?ver=- men erstatt cache-busting. - Sett X-Frame-Options, nosniff, HSTS, CSP (start report-only) og Referrer-Policy.
- Blokker
xmlrpc.phphvis ubrukt. - Stram filrettigheter, spesielt
wp-config.php. - Rate-limit + 2FA på innlogging.
- Verifiser med curl og securityheaders-sjekk etter deploy.
Skjul versjonen for å falle ut av billige skannere. Sett headers for å stoppe angrep nettleseren faktisk kan blokkere.






