PHP2Shell Check (CVE-2026-109618 · CVE-2026-109619)
A free, open-source tool that checks non-destructively whether the PHP sites you run are exposed to PHP2Shell.
Free · MITPython 3.8+ stdlib onlyNo attack trafficReports in English · 한국어 · 日本語
What is PHP2Shell
Two PHP runtime vulnerabilities disclosed on 2026-10-21, both rated CVSS v4.0 9.2. They lead to unauthenticated remote code execution (RCE), and virtually every PHP installation that serves web requests (Apache mod_php, PHP-FPM, …) is affected. Public PoCs exist, and real attack attempts were observed from 10-17, four days before disclosure.
| PHP branch | Fixed in |
|---|---|
| 8.5 | 8.5.12 or later |
| 8.4 | 8.4.27 or later |
| 8.3 | 8.3.36 or later |
| 8.2 | 8.2.35 or later |
| 8.1 and older | No official fix release — use distro/LTS vendor packages or upgrade |
Distribution packages (e.g. 8.2.7-1+deb12u5) may carry backported fixes despite a lower version number. Baseline as of 2026-10-23. Details: PHP vulnerability trends §2
Step 1 — Triage from your site's URL
Enter your site's address and this page builds a command to run on your own computer. The checker sends a single HTTP GET to the target and compares the PHP version exposed in the response headers against the fixed versions.
Reading the result
| Verdict | Meaning |
|---|---|
likely_vulnerable | The exposed PHP version is below the fixed version, or is an EOL branch (below 8.2) with no official fix. Confirm with Step 2. |
not_vulnerable_by_version | The exposed version is at or above the fixed baseline. A supporting signal only, not a guarantee. |
unknown | PHP traces found but the version is hidden (or only partially shown, like 8.3). |
not_detected | No PHP traces in the response. This does not mean PHP is absent. |
error / invalid | Connection/TLS error, or malformed URL. |
Production servers usually hide the version, so unknown is common. The version alone cannot tell whether an attack path actually holds; if you have server access, run Step 2.
Step 2 — Confirm on the server
Run this on the (Linux) server running PHP. It only reads configuration files, package data, /proc and logs — zero commands executed, zero network requests. It decides per-CVE reachability from the SAPI (mod_php/FPM) and effective settings (memory_limit, session.upload_progress.enabled, …) and reports which file and line to fix.
curl -fsSLO https://raw.githubusercontent.com/neoqmin/php2shell/v0.1.0/php2shell_host.py echo '50a48c79c120774e9dccc27ee12672444b7730b31a32c2b833e650920ebf0925 php2shell_host.py' | sha256sum -c - sudo python3 php2shell_host.py --lang en
Output goes to ./php2shell_report_<host>/ as report.json, report_en.md and report_en.html (A4 printable). The report contains the server's vulnerability details — do not publish it.
Sample report (local lab, no real target): HTML · Markdown · JSON
| Verdict | Meaning |
|---|---|
| Reachable | The attack path's preconditions hold given this server's SAPI and effective configuration |
| Mitigated (temporary) | A temporary mitigation is applied before request parsing. Not safe — configuration alone does not fully mitigate |
| Undetermined | Insufficient evidence or failed to read config. This is not "unreachable" |
| Patched | At or above the fixed version, or the package changelog records a backport of both CVEs |
Supported: Debian/Ubuntu packages (Apache mod_php, nginx/Apache + PHP-FPM) and the official Docker php:*-apache image. RHEL-family package versions, the official php:*-fpm image, php-cgi, LiteSpeed and FrankenPHP are not assessed yet. See the README for all options and limitations.
If you cannot patch right now
Updating PHP is the only complete fix. Temporary mitigations until then (session.upload_progress.enabled=0, tuning memory_limit/post_max_size, blocking multipart, …) only work when set where they apply before request parsing, such as php.ini or the FPM pool. ini_set() and FPM .user.ini have no effect. The Step 2 report tells you where to change each server. Source: trends §2.6
FAQ
If the remote check says not_vulnerable_by_version, am I safe?
No. It only means the version shown in the headers meets the baseline; proxies and load balancers can mask the version, and SAPI and settings cannot be seen remotely. Make the final call from your server inventory and Step 2.
How do I check a server that hides its version (unknown)?
You can't from outside. On the server, check php -v and the package changelog, or run the Step 2 checker.
Can I check another company's site?
Not without permission. Even a single non-destructive GET, done systematically without authorization, may break computer-misuse laws. If you notice a problem on someone else's server, do not verify it yourself — notify the operator or your national CERT.
What does the tool collect or send?
Nothing. The remote checker sends one GET to the target you enter; the host checker makes no network requests. The report's transparency appendix lists every file it read.
Does it contain exploit (PoC) code?
No. It contains no payloads, exploits or bypass techniques, and does not link to exploit repositories.