Zum Inhalt

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_memory abgelehnt. 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 off streamen 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.