Auf den meisten Hosts ist der richtige Weg zum Schutz von wp-admin/install.php eine Regel in Apache oder nginx, oder ein Pre-WordPress-Firewall-Plugin wie Wordfence (Extended Protection) oder NinjaFirewall. Im Shared-nginx-Hosting hast du aber manchmal keinen Zugriff auf die Server-Config, und Core-Updates stellen die Datei wieder her, selbst wenn du sie löschst oder ersetzt. Dieses Snippet geht den Umweg: ein Must-Use-Plugin, das install.php von innerhalb von PHP unschädlich macht, ohne die Datei selbst anzufassen.
Warum ein Must-Use-Plugin?
Must-Use-Plugins liegen im Ordner wp-content/mu-plugins/ und werden bei jedem Request automatisch geladen, noch vor den normalen Plugins und bevor irgendwelcher Frontend-Code läuft. Sie lassen sich im WP-Backend nicht deaktivieren, und WordPress-Core-Updates tasten sie nicht an. Damit sind sie der richtige Ort für kleine Stücke "immer aktiven" Code.
Das Snippet unten fängt Requests auf install.php in der Plugin-Ladephase ab, sendet ein 403 und beendet die Ausführung, bevor WordPress den Setup-Assistenten rendern würde.
Das Snippet
Lege eine Datei unter wp-content/mu-plugins/disable-install-php.php an (den Ordner mu-plugins musst du ggf. selbst erstellen) mit folgendem Inhalt:
<?php
/**
* Plugin Name: install.php deaktivieren
* Description: Gibt auf jeden Request an wp-admin/install.php ein 403 zurück.
*/
if (!defined('ABSPATH')) {
exit;
}
add_action('muplugins_loaded', function () {
$requestUri = isset($_SERVER['REQUEST_URI']) ? (string) $_SERVER['REQUEST_URI'] : ';
$path = parse_url($requestUri, PHP_URL_PATH);
if (is_string($path) && preg_match('#/wp-admin/install\.php$#', $path)) {
status_header(403);
nocache_headers();
header('Content-Type: text/plain; charset=utf-8');
echo 'Forbidden';
exit;
}
});Wie es funktioniert
- muplugins_loaded feuert vor den regulären Plugins und bevor WordPress die Ausführung an
install.phpübergibt. Das ist früh genug, um den Request sauber zu blockieren. - parse_url + Regex prüft gezielt den Pfad. Wir suchen bewusst nicht einfach nach dem Substring
install.php, um nicht versehentlich legitime Admin-URLs zu blockieren, die den String zufällig als Query-Parameter enthalten. - status_header(403) + nocache_headers() sorgt dafür, dass die Antwort als "verboten" gewertet und nicht von Proxies, CDNs oder Browser-Caches zwischengespeichert wird.
Warum das nur ein Fallback ist, keine Haupt-Verteidigungslinie
Das läuft innerhalb von PHP, funktioniert also nur, solange WordPress selbst noch startet. In genau dem Szenario, in dem install.php gefährlich wird (defekte oder leere Datenbank), kann es sein, dass WordPress vor diesem Code aussteigt und die Datei direkt ausgeliefert wird. Deshalb ist eine Webserver-Regel oder eine Pre-WordPress-Firewall (Wordfence Extended Protection, NinjaFirewall, BitFire, Shield, MalCare) immer vorzuziehen.
Dieses Snippet ist die richtige Wahl, wenn weder eine Webserver-Regel noch ein Pre-WordPress-Firewall-Plugin realistisch machbar ist: abgeschottetes Shared Hosting, auf dem auto_prepend_file nicht zugelassen ist, kein ansprechbarer Support, keine Möglichkeit, eine Regel eintragen zu lassen. Besser als nichts, und in der Praxis (wo die Datenbank zu 99,9% einfach funktioniert) blockiert es zumindest automatisierte Scanner und Exploit-Versuche, die den Endpunkt von außen abklopfen.
Prüfen
Rufe https://deinedomain.de/wp-admin/install.php in einem privaten Browserfenster auf. Du solltest eine schlichte 403 Forbidden-Antwort sehen. Wenn stattdessen die "Bereits installiert"-Seite erscheint: prüfen, ob die Datei tatsächlich in wp-content/mu-plugins/ liegt (nicht im normalen plugins/-Ordner) und ob die Dateirechte PHP das Lesen erlauben.