Zum Hauptinhalt springen

Eine saubere Webserver-Konfiguration ist die Basis jeder sicheren WordPress-Installation. Viele Härtungsmassnahmen lassen sich direkt auf dem Webserver umsetzen. Das ist effizienter als per Plugin, weil Anfragen gar nicht erst PHP erreichen.

Nginx: Grundkonfiguration

server {
    server_name example.ch;
    root /var/www/example/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm-example.sock;
    }

    # Keine PHP-Ausführung in Uploads
    location ~* /wp-content/uploads/.*\.php$ { deny all; }

    # Sensible Dateien sperren
    location ~* /(wp-config\.php|readme\.html|license\.txt|\.git|\.env|debug\.log) { deny all; }
    location = /xmlrpc.php { deny all; }

    # Statische Assets lange cachen
    location ~* \.(css|js|woff2|svg|png|jpg|jpeg|webp|avif)$ {
        expires 1y; add_header Cache-Control "public, immutable"; access_log off;
    }
}

Apache: .htaccess-Ergänzungen

# Sensible Dateien sperren
<FilesMatch "^(wp-config\.php|readme\.html|license\.txt|debug\.log|xmlrpc\.php)$">
    Require all denied
</FilesMatch>

# Verzeichnislisting aus
Options -Indexes

In wp-content/uploads/.htaccess:

<FilesMatch "\.(php|phtml|phar)$">
    Require all denied
</FilesMatch>

Bei Apache ist eine Konfiguration im VirtualHost performanter als .htaccess, weil die Dateien sonst bei jedem Request gelesen werden (AllowOverride None, wenn möglich).

Rate Limiting für Login

Nginx:

limit_req_zone $binary_remote_addr zone=wplogin:10m rate=5r/m;
location = /wp-login.php {
    limit_req zone=wplogin burst=5 nodelay;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php8.3-fpm-example.sock;
}

TLS und HTTP/2/3

  • Nur TLS 1.2 und 1.3, moderne Cipher (z. B. Mozilla SSL Configuration Generator, Profil „Intermediate“).
  • HTTP/2 aktivieren, HTTP/3 (QUIC) wo verfügbar.
  • HSTS erst setzen, wenn HTTPS überall sicher funktioniert (siehe Sicherheits-Header).

Tipp

Nach jeder Änderung testen: nginx -t bzw. apachectl configtest, danach mit curl -I https://example.ch/xmlrpc.php prüfen, ob die Sperre greift (erwartet: 403).

Weiterführende Artikel

Quellen und Dokumentation