phpguard: Ungeschütztes PHP vor php2shell-Multipart-Angriffen abschirmen
Erfordert den Pro-Plan (oder höher) des GetPageSpeed NGINX Extras-Abonnements.
Installation
Sie können dieses Modul in jeder RHEL-basierten Distribution installieren, einschließlich, aber nicht beschränkt auf:
- RedHat Enterprise Linux 7, 8, 9 und 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 und Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-phpguard
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-phpguard
Aktivieren Sie das Modul, indem Sie Folgendes am Anfang von /etc/nginx/nginx.conf hinzufügen:
load_module modules/ngx_http_phpguard_module.so;
Dieses Dokument beschreibt nginx-module-phpguard v1.0.0 veröffentlicht am 12. November 2026.
Ungeschütztes PHP vor php2shell abschirmen (CVE-2026-109618, CVE-2026-109619 und CVE-2026-115560) auf der NGINX-Ebene, ohne PHP anzufassen.
php2shell wird über PHPs eigenen multipart/form-data-Parser erreicht. Dieser Parser läuft vor jedem Anwendungscode und vor jedem Login, sodass jeder PHP- Endpunkt exponiert ist. Einfache NGINX-Regeln können nur alle Multipart- Anfragen blockieren, was Uploads bricht, und sie übersehen die Kodierungen, die PHP akzeptiert.
phpguard liest jeden Multipart-Body in NGINX, bevor PHP ein einziges Byte
sieht, und prüft ihn mit einem Streaming-Parser, der PHPs eigenem entspricht.
Es wurde auf PHP 5.6, 7.4, 8.1, 8.4 und 8.5 verifiziert, hinter PHP-FPM und
hinter Apache mod_php über proxy_pass.
Was es blockiert
- Das Session-Upload-Progress-Feld, der bestätigte php2shell-Auslöser, in jeder Schreibweise, die PHP akzeptiert: in Anführungszeichen oder nicht, beliebige Groß-/Kleinschreibung, gefaltete Header, LF-only-Zeilen, Komma-Content-Types, Chunked-Bodies und HTTP/2.
- Eingeschmuggelte Parts. Nur kanonisches Multipart wird akzeptiert. Eine Präambel, ein Epilog, NUL- oder Steuerbytes, mehrdeutige Quotierung oder eine Boundary-Zeichenkette an jeder Stelle außer einem echten Delimiter wird abgelehnt. Das schließt den Part ein, den PHP nach 5120 Bytes findet, wenn es einen Upload überspringt, den es nicht behält.
- Out-of-Memory-Parses. Der Parse-Speicher jeder Anfrage in PHP wird
mit einem Kostenmodell geschätzt, das auf jeder unterstützten PHP-Version
gemessen wurde, und die Anfrage wird oberhalb von
phpguard_max_memoryabgelehnt. Leere Datei-Eingaben mit tief verschachtelten Namen können andernfalls PHP dazu bringen, über 100 MB für wenige Kilobytes Eingabe zu allokieren.
Nur Multipart-Anfragen werden inspiziert. GET-, JSON- und URL-kodierte Formulare kosten eine einzige Header-Prüfung.
Konfiguration
Aktivieren Sie es für den gesamten Server, damit der Body dort geprüft wird, wo er zuerst gelesen wird:
server {
phpguard block;
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm.sock;
include fastcgi_params;
}
}
Beginnen Sie mit phpguard detect;, um zu protokollieren, was abgelehnt
würde, ohne etwas zu blockieren.
Direktiven
| Direktive | Standard | Kontext | Beschreibung |
|---|---|---|---|
phpguard off \| detect \| block |
off |
http, server, location | block (Alias on) lehnt ab; detect protokolliert nur |
phpguard_status <code> |
403 |
http, server, location | Status für Richtlinien-Ablehnungen (400-599). Fehlerhafte Bodies erhalten immer 400 |
phpguard_progress_name <name> |
PHP_SESSION_UPLOAD_PROGRESS |
http, server, location | Feldname, der abgelehnt wird; für mehrere wiederholen. Setzen Sie ihn, wenn session.upload_progress.name geändert wird |
phpguard_max_memory <size> |
32m |
http, server, location | Geschätzter PHP-Parse-Speicher pro Anfrage. Halten Sie ihn deutlich unter Ihrem kleinsten memory_limit |
phpguard_max_parts <n> |
1000 |
http, server, location | Parts pro Body |
phpguard_max_name_length <n> |
512 |
http, server, location | Bytes in einem Feldnamen |
phpguard_max_nesting <n> |
32 |
http, server, location | [-Ebenen in einem Feldnamen |
Die Variable $phpguard enthält den Ablehnungsgrund (leer, wenn die Anfrage
durchgelassen wurde), zum Beispiel in einem log_format.
Hinweise
- PHPs Upload-Progress-Balken (
session.upload_progress) funktionieren nicht mehr, da ihr Feld genau das ist, was abgelehnt wird. - Multipart-Bodies werden vollständig gepuffert, bevor PHP sie erhält. Das
ist NGINXs Standard; mit
fastcgi_request_buffering offstreamen Uploads nicht mehr zu PHP. - Ein Feld- oder Dateiname, der mit einem Backslash endet, wird abgelehnt. PHP parst solche Namen ohnehin falsch.
- phpguard deckt die anfragegebundenen Multipart-Pfade von php2shell ab. Es behebt PHP nicht: Out-of-Memory-Fehler, die Ihre Anwendung über andere Eingaben erreicht, und zukünftige PHP-Bugs außerhalb des Multipart-Parsers bleiben bestehen. Aktualisieren Sie PHP, wenn Sie können.