← Back to Tools

PHP2Shell CVE Checker

How We Scan: Full Analysis →

Checks a domain for exposure to the php2shell remote code execution vulnerabilities (CVE-2026-109618 / CVE-2026-109619) and the related unpatched flaw CVE-2026-115560.

▶ What this tool checks

Standard checks (always run)

  • PHP version from X-Powered-By / Server headers and PHP error pages; assessed against CVE-2026-109618, CVE-2026-109619, and GH-24488 (GC regression in 8.4.27 and 8.5.12)
  • Multipart POST acceptance on /index.php (one CVE-2026-109619 attack path)
  • Common phpinfo paths (/phpinfo.php, /info.php, etc.) for an exposed configuration page
  • phpMyAdmin endpoint (/show_config_errors.php), a confirmed exploitation path

When a phpinfo page is found, also reads:

  • Server API (SAPI) and server software
  • file_uploads, display_errors, allow_url_include (On/Off)
  • session.upload_progress.enabled, session.upload_progress.cleanup, session.use_strict_mode, session.use_only_cookies, and session.serialize_handler
  • memory_limit: the published exploit is tuned for 8M; low values increase risk
  • max_input_vars: the exploit uses 1000 fields to trigger OOM
  • post_max_size: caps multipart body size; determines maximum forced allocation
  • fatal_error_backtraces (PHP 8.5+): stack traces on fatal errors can leak heap metadata
  • open_basedir and disable_functions (post-exploitation constraints; note that Chain B bypasses disable_functions entirely)

Active crash probe (opt-in, requires email verification)

Simulates a real PoC request to test for crash behaviour. Sends a ~90 KB nested multipart body to /index.php and checks for empty HTTP 500 or PHP OOM error signatures. Requires verifying ownership of the target domain via email before running.

Read the full technical reference: every check, the vulnerability mechanics, and what results mean →

▶ Enable Active Crash Probe (Optional) - Simulates a real PoC request to test for crash behaviour

Sends a ~90 KB nested multipart body to /index.php and checks for PHP OOM crash signatures. On a vulnerable server this may disrupt worker processes, cause brief service interruption, or trigger security alerts. Only enable if you have explicit permission to perform active testing.

▶ Scan authorisation and risk acknowledgment
By initiating a scan you confirm that you own or are explicitly authorised to test the target system, that you understand the potential risks, and that you accept responsibility for initiating the scan. To the maximum extent permitted by applicable law, WebInspect.pro and its operators disclaim liability for service disruptions, server crashes, data loss or other damages arising from the use of this tool. Scan results are provided for informational purposes only, without warranties of accuracy, completeness or fitness for a particular purpose.

Stay Updated on PHP2Shell Security

Receive updates about new findings, patch releases, and tool changes. No marketing — security notices only.

▶

Important: Detection Limitations

PHP version detection uses response headers, error pages, exposed phpinfo files and phpMyAdmin endpoints. If none of these disclose a version, we cannot assess patch status. A hidden version does not mean the server is safe.

The crash probe (opt-in) sends a nested multipart body (~90 KB) and checks for OOM or error signatures. On a vulnerable server it may disrupt PHP worker processes, cause brief service interruption, or trigger security monitoring on the target. It cannot confirm exploitation, and a clean result does not rule out vulnerability.

The multipart acceptance check covers one CVE-2026-109619 attack path only. phpinfo and phpMyAdmin checks rely on those files being publicly accessible.

A clean result does not guarantee the server is unaffected. Always verify your installed PHP version and confirm patches with your hosting provider. Note: upgrading PHP alone does not fully close all attack paths. The config changes in the mitigation section below are also required.

▶

About CVE-2026-109618, CVE-2026-109619 & CVE-2026-115560

CVE-2026-109618 is an out-of-memory corruption flaw. An OOM event during request initialisation leaves internal PHP data structures in an invalid state. When PHP's cleanup routine runs after the abort it may process those dangling pointers, enabling remote code execution. Any request type can trigger the OOM condition.

CVE-2026-109619 is a stale global state flaw. After a request ends, request-owned state is not always fully cleared. A later request on the same worker can reference that freed memory through session upload progress, allowing an attacker to inject controlled data. PHP parses multipart bodies before application code runs, so the vulnerability is reachable even on sites with no file upload feature.

The published working exploit targets Apache prefork with mod_php specifically, though the underlying flaw affects all SAPIs including PHP-FPM, FrankenPHP, and LiteSpeed. It uses a two-stage ASLR bypass: an OOM event during request handling leaves a dangling pointer; a follow-up request triggers a bounded out-of-bounds read that leaks heap addresses and the PHP library base address through oversized Set-Cookie response headers. A fake destructor table is then placed at the leaked address to redirect execution to an internal system() equivalent. The current published PoC works against stock php.ini-production settings (display_errors=Off, memory_limit=128M) and does not require error output. An earlier version of the exploit required display_errors=On and memory_limit=8M; that version is now archived.

On PHP 8.5, fatal_error_backtraces is a new ini directive. When enabled (the default), stack traces included in fatal error responses can leak internal heap metadata. This provides an additional information-disclosure path that assists the CVE-2026-109619 ASLR bypass on PHP 8.5 servers.

A separate attack path documented in researcher analysis does not require memory corruption at all. An attacker writes a serialized PHP object into the session file (for example by placing it in the session.upload_progress.name field). PHP deserializes that value before application code runs (before RINIT), so any gadget class present on the server, including those from WordPress, Laravel, and other common frameworks, can be triggered through its __destruct() method. The result is a stable code execution path that bypasses WAFs, middleware, and ini_set() calls because none of those run in time.

Both CVEs are fixed in PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35. For PHP 8.1, 8.0 and 7.4 backports are available via distribution package managers. PHP 5.x has no patch. Note: upgrading PHP alone does not fully close the deserialization and session fixation paths (Chains A and C); the config changes below are also required.

CVE-2026-115560 is a separate, currently unpatched flaw disclosed on 23 October 2026. It requires three conditions together: session.serialize_handler is set to php_binary or php_serialize in php.ini; the application then switches it back to php via ini_set() at runtime before calling session_start(); and session.upload_progress.enabled is on. Applications that never switch the handler at runtime are not exposed through this path. No patch exists yet; PHP plans to ship the fix in its next regular release. The mitigation is the same as for the php2shell flaws: set session.upload_progress.enabled = 0 in php.ini and restart workers. We can check the php.ini value of session.serialize_handler when a phpinfo page is exposed, but we cannot detect runtime ini_set() changes made by application code.

▶

Interim mitigations (until patched)

Block multipart POST requests at the web server layer. This covers one CVE-2026-109619 path but does not address CVE-2026-109618:

# Apache (.htaccess or VirtualHost)
<If "%{CONTENT_TYPE} =~ m#^multipart/form-data#i">
  Require all denied
</If>

Disable session upload progress in php.ini (must restart every worker; ini_set() is not sufficient). This blocks the deserialization and session fixation attack paths (Chains A and C) even on a patched PHP version, and is also the only available mitigation for the unpatched CVE-2026-115560:

session.upload_progress.enabled = 0

This must be set in php.ini or an FPM pool configuration file. Setting it in .user.ini does not work: per-directory ini files are applied after request initialisation (RINIT), which is when the upload progress handler runs. A .user.ini value is processed too late to prevent the write.

If your application uses sessions in multiple directories with different serialization handlers, ensure session.serialize_handler is consistent across all of them. A mismatch allows an attacker to write data under one handler and have it deserialized under another (Chain C).

For CVE-2026-115560 specifically: audit your codebase for any ini_set('session.serialize_handler', ...) calls. The vulnerability requires switching the handler to php at runtime after it was set to php_binary or php_serialize in php.ini. Removing those runtime switches eliminates the trigger condition regardless of patch status.

Keep session.save_path outside the web root. If sessions are stored in a web-accessible directory, an attacker who injects code via upload_progress (Chain A) can execute it with a direct HTTP request rather than needing an LFI vulnerability in your application.