OpenAIs php2shell-checker eignet sich für eine erste Einschätzung, beweist aber nicht, dass ein Server sicher ist. Das Tool vergleicht eine per HTTP-Header oder über php -v ermittelte PHP-Version mit fest hinterlegten Versionsgrenzen. Ein ausgeblendeter Header kann deshalb zu UNKNOWN führen, während ein Distribution-Backport einen bereits gepatchten Server fälschlich als verwundbar erscheinen lässt.
Was die Ergebnisse bedeuten
Das offizielle OpenAI-Repository kennt drei relevante Zustände. Sie sind als Hinweise für die Triage gedacht, nicht als vollständige Schwachstellenprüfung.
| Ausgabe | Exit-Code | Aussage | Nächster Schritt |
|---|---|---|---|
OK | 0 | Der erkannte Branch entspricht mindestens der festgelegten Version, ab der der Fix enthalten ist | Prüfen, ob der PHP-Prozess für den Webverkehr tatsächlich diese Version verwendet |
VULNERABLE | 1 | Die erkannte Version liegt unterhalb der minimalen Fix-Version | Die Laufzeitumgebung aktualisieren, ihre Worker neu starten und beide Prüfungen erneut ausführen |
UNKNOWN | 3 | Das Tool konnte keine bekannte Version oder verwertbare Antwort ermitteln | Den Server lokal untersuchen und das Ergebnis nicht als gepatcht werten |
| Ungültige Argumente | 2 | Der Befehl selbst war nicht gültig | Den Befehl korrigieren und erneut ausführen |
Was OpenAI liefert
Das öffentliche php2shell-checker-Repository enthält ein Node.js-Skript, Tests und zwei Codex-Skills: phpcheck-url für eine erreichbare Website sowie phpcheck-server für Server, auf die du Zugriff hast. Das Tool sammelt Versionshinweise; es nutzt kein Ziel aus und scannt auch keinen Anwendungscode.
Den passenden Prüfmodus wählen
Eine öffentliche URL prüfen
Repository klonen oder herunterladen und anschließend das Node.js-Skript gegen eine Website ausführen:
node phpcheck.js "https://example.com"
Die Fernprüfung sendet zunächst eine HTTP-HEAD-Anfrage und wechselt nur dann zu GET, wenn der Server mit 405 oder 501 antwortet. Ausgewertet werden X-Powered-By und Server. Weiterleitungen verfolgt das Tool nicht, und den Response-Body untersucht es ebenfalls nicht.
Ein CDN, ein Reverse Proxy, expose_php=off oder eine eigene Serverkonfiguration kann die PHP-Version entfernen, bevor die Antwort den Checker erreicht. Bei VULNERABLE ist ein Patch erforderlich; fehlt der Header, brauchst du Belege direkt vom Server.
Eine lokale PHP-Binary prüfen
Auf einem Rechner mit installierter PHP-Version genügt:
node phpcheck.js --local
Damit wird php -v für die Binary ausgeführt, die im aktuellen PATH gefunden wird. Das beweist nicht, dass dieselbe Binary auch deine Website bedient. Auf einem Host können CLI, PHP-FPM, CGI, Apache-Modul, Container oder selbst kompilierte Installationen parallel existieren.
Nach der lokalen Prüfung musst du die Laufzeitumgebung identifizieren, die mit dem Webserver verbunden ist. In einer containerisierten Umgebung solltest du den laufenden Container untersuchen und dich nicht nur auf den Image-Tag verlassen. Bei einem paketierten Dienst gehören außerdem der zuständige PHP-FPM-Pool oder das Apache-Modul sowie das Changelog des Anbieters auf die Prüfliste.
Codex-Skills installieren und verwenden
Die offizielle README installiert beide Skills mit einem einzigen Codex-Befehl:
$skill-installer install both skills from https://github.com/openai/php2shell-checker
Danach wählst du die Schnittstelle passend zu deinen Zugriffsrechten:
$phpcheck-url check https://example.com
$phpcheck-server check the PHP version serving my site
Codex ist optional. Für CI-Jobs und schlanke Systeme bleibt der Node.js-Befehl die direkte Schnittstelle. Für Automatisierung ergänzt du --json. Das Feld patch_status liefert dann ok, vulnerable oder unknown, sodass ein Skript keine Terminaltexte parsen muss.
Den heruntergeladenen Checker testen
Das Repository verwendet den integrierten Test-Runner von Node:
node --test phpcheck.test.js
Die Tests prüfen die CLI gegen lokale HTTP-Server und verwenden für lokale Szenarien eine gefälschte PHP-Executable. Laut README sind dafür weder eine echte PHP-Installation noch der Zugriff auf eine externe Website erforderlich.
UNKNOWN als Debugging-Hinweis verstehen
Behandle UNKNOWN als unvollständige Datenlage. Das Ziel kann seine PHP-Version verbergen, einen nicht erkannten Branch verwenden, nicht antworten oder eine neuere Vorabversion einsetzen. Keine dieser Situationen belegt, dass der Fix vorhanden ist.
Ein echter Nutzer, @jvr0x, fasste die Einschränkung so zusammen:
„Es handelt sich lediglich um einen Versionsvergleich mit den Grenzwerten vom 20. Oktober – ausgeblendete Header führen deshalb zu UNKNOWN.“
Der Remote-Befehl sieht nur die HTTP-Antwort, nicht den Prozess hinter dem Reverse Proxy. Wenn der Header verborgen wird, hilft keine weitere URL-Abfrage; du brauchst stattdessen eine Prüfung auf dem Server.
Nach einem UNKNOWN gehst du am besten so vor:
node phpcheck.js --localauf dem Host ausführen, der die Website bedient.- Feststellen, ob die Anfrage PHP-FPM, CGI, Apache
mod_phpoder einen Container erreicht. - Das Changelog des Anbieters auf Backports prüfen.
- Nach der Aktualisierung die zuständigen PHP-FPM- oder Apache-Worker neu starten.
- Über den tatsächlichen Auslieferungspfad prüfen – nicht nur über die standardmäßig im Shell-Kontext verwendete
php-Binary.
Ohne SSH bleibt der URL-Modus möglicherweise der einzige erste Prüfpunkt. Unterdrückt ein Shared-Hosting-Anbieter den Versions-Header, muss er die eingesetzte Laufzeitumgebung, die Paketversion und den Status des Neustarts bestätigen.
Die Versionstabelle entscheidet nicht allein über den Patch-Status
Der Checker behandelt PHP 8.5.12, 8.4.27, 8.3.36 und 8.2.35 als minimale behobene Upstream-Versionen der jeweiligen Branches. Die offiziellen Tests bestätigen, dass 8.4.26 als VULNERABLE und 8.4.27 als OK eingestuft wird. PHP führt 8.5.12, 8.4.27, 8.3.36 und 8.2.35 als Security-Releases.
| Branch | Minimale behobene Upstream-Version | Vorherige, als verwundbar eingestufte Version |
|---|---|---|
| PHP 8.5 | 8.5.12 | 8.5.11 |
| PHP 8.4 | 8.4.27 | 8.4.26 |
| PHP 8.3 | 8.3.36 | 8.3.35 |
| PHP 8.2 | 8.2.35 | 8.2.34 |
| Deployment-Situation | Warum ein einfacher Versionsvergleich irreführen kann | Heranzuziehende Belege |
|---|---|---|
Verborgener X-Powered-By- oder Server-Header | Der Remote-Checker kann PHP nicht identifizieren | Lokare Bestandsaufnahme der Laufzeitumgebung |
| Debian- oder Ubuntu-Sicherheitspaket | Der Anbieter kann den Fix unter einer älteren Upstream-Versionsnummer zurückportiert haben | Security-Hinweis des Anbieters und Paket-Changelog |
| PHP-FPM und CLI auf demselben Host | php -v beschreibt möglicherweise die CLI und nicht den HTTP-Worker | Webserver- und FPM-Konfiguration |
| Gecachter Container oder angehefteter Digest | Der Registry-Tag kann aktuell sein, während der laufende Container noch alt ist | Image-ID und Version des laufenden Containers |
| Apache- oder FPM-Worker nicht neu gestartet | Die gepatchten Dateien können zwar auf der Festplatte liegen, während ältere Worker weiterhin aktiv sind | Prozessstartzeit und Prüfung nach dem Neustart |
| Nicht unterstützter Branch oder Vorabversion | Der Checker erkennt den Patch-Status des Anbieters möglicherweise nicht | PHP- oder Security-Hinweis des Anbieters |
Im Limitations-Abschnitt des Repositorys steht, dass das Tool davon ausgeht, spätere stabile Patches eines gelisteten Branches enthielten den Fix. Unabhängig verifizieren kann es den Fix nicht. Eine Distribution kann einen Security-Backport einspielen, ohne die Upstream-Versionsnummer zu ändern. In diesem Fall ist das Changelog aussagekräftiger als die angezeigte Versionsnummer allein.
Ein Update von WordPress, Drupal, Laravel oder einer anderen PHP-Anwendung schließt keine Lücke in der PHP-Engine. Aktualisiere das Laufzeitpaket oder Image, starte die Worker neu und prüfe anschließend den Prozess, der Webanfragen entgegennimmt.
FAQ
Welches Ergebnis reicht aus, um ein Produktions-Ticket zu schließen?
Kein einzelnes Ergebnis sollte ein Ticket automatisch schließen. Kombiniere OK mit der tatsächlich verwendeten SAPI, dem Backport-Status des Anbieters, allen relevanten VHosts oder Containern und der Bestätigung, dass die Worker nach dem Patch neu gestartet wurden.