In PHP laden die Anweisungen include und require (und ihre Varianten mit _once) eine Datei und führen den darin enthaltenen Code aus. Sie werden überall eingesetzt, zum Beispiel um ein Template des Themes zu laden. Gefährlich wird es, wenn der Dateipfad von Daten abhängt, die der Besucher sendet, ohne dass sie ausreichend geprüft werden. Der Katalog von MITRE führt diese Schwäche als CWE-98, mit zwei gängigen Bezeichnungen: RFI für die entfernte, LFI für die lokale Einbindung.
So läuft der Angriff ab
Code wie dieser lässt den Besucher auswählen, welche Datei geladen wird:
// Bitte nicht so
include( __DIR__ . '/templates/' . $_GET['view'] . '.php' );
- LFI (Local File Inclusion): Mit Sequenzen wie
../klettert der Angreifer im Verzeichnisbaum nach oben und lässt eine Datei laden, die bereits auf dem Server liegt. Im besten Fall liest er eine Datei, die er nicht sehen dürfte; gelingt es ihm, eine Datei einzubinden, deren Inhalt er kontrolliert (ein Log, eine hochgeladene Datei), erreicht er eine Remote Code Execution. - RFI (Remote File Inclusion): Der Angreifer liefert eine URL, die auf seinen eigenen Server zeigt, und PHP bindet seinen Code direkt ein. Das ist die direkteste Form, sie setzt aber eine Einstellung voraus, die selten aktiviert ist.

Die Rolle der PHP-Konfiguration
Die PHP-Dokumentation ist bei zwei Direktiven eindeutig:
allow_url_includeerlaubt URLs inincludeundrequire. Der Standardwert ist0, die Einstellung lässt sich nur in der Systemkonfiguration (php.ini) ändern und ist seit PHP 7.4.0 veraltet. Außerdem mussallow_url_fopenaktiviert sein.allow_url_fopenerlaubt PHP, URLs wie Dateien zu öffnen; die Option ist standardmäßig aktiv, weil viele Skripte sie brauchen.
RFI abzuschalten löst nicht alles: PHP-Wrapper wie php://filter können manche LFI-Lücken auf einer Standardkonfiguration in Codeausführung verwandeln, und phar:// diente lange dazu, eine unsichere Deserialisierung auszulösen. Unser Beitrag zu den Wrappern php://filter und phar erklärt diese Techniken im Detail.
So schützt du dich
Die beste Abwehr, von MITRE empfohlen, besteht darin, nie einen Pfad aus empfangenen Daten zusammenzusetzen, sondern feste Werte bekannten Dateien zuzuordnen:
$views = array( 'list' => 'list.php', 'grid' => 'grid.php' );
$view = isset( $views[ $_GET['view'] ?? '' ] ) ? $views[ $_GET['view'] ] : 'list.php';
include __DIR__ . '/templates/' . $view;
- Leg eingebundene Dateien nach Möglichkeit außerhalb des Web-Roots ab.
- Begrenze mit
open_basedir, was PHP lesen darf: Ein umgeleitetes include kann die erlaubten Verzeichnisse dann nicht verlassen. PHP auf deinem Hosting härten erklärt diese Einstellung und ihre Auswirkungen. - Eine Web Application Firewall blockiert typische Muster (
../,php://), allerdings nur als zusätzliche Schicht.
Für WordPress
Der WordPress-Core setzt seine includes nicht aus Besucherparametern zusammen: Das Risiko geht von Plugins und Themes aus, die ein Template, eine Sprachdatei oder ein Modul anhand eines URL- oder AJAX-Parameters laden. Das liebste LFI-Ziel ist wp-config.php mit den Zugangsdaten zur Datenbank und den Sicherheitsschlüsseln; eine im Web-Root vergessene sensible Datei, etwa eine .env-Datei oder ein Backup, ist ebenfalls leichte Beute, wie unser Beitrag über offen zugängliche sensible Dateien zeigt. Prüfe schließlich, dass dein Hoster allow_url_include deaktiviert lässt.