php2shell check — https://news.ycombinator.com

3 min read Original article ↗

php2shell.site active development

php2shell check — patch & mitigation status for CVE-2026-109618 / CVE-2026-109619, two critical unauthenticated remote-code-execution bugs in PHP, for URLs you are authorized to test. All verdict logic runs locally in your browser — the server only relays raw HTTP facts.

advisory out now — update PHP php.net, 21 Oct 2026: Critical remote code execution vulnerabilities, update now · details ▾

Fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (source, Windows; Linux distributions and LTS vendors got the patches in advance — check your vendor). At risk: every PHP installation serving web requests — PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed; highest for mod_php, where an unauthenticated request can trigger the attack before any application code runs.
CVE-2026-109618 (GHSA-w8hw-w9fx-j79w): RCE via out-of-memory corruption during request setup. CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp): RCE via stale global state reused by a later request on the same worker.
PHP 8.1 and older get no release from the PHP project: use your vendor’s backport or upgrade; minimal source backports exist for 7.4, 8.0 and 8.1. Using rpms.remirepo.net? It has no update today — switch to distribution packages or build from source.

If you cannot update immediately (reduces exposure, does not make PHP safe)

CVE-2026-109618 (OOM corruption):

  • memory_limit=-1, set where applications can’t override it (e.g. php_admin_value in the FPM pool or Apache config); make sure no pool/directory/app setting brings a finite limit back.
  • Low post_max_size: 8M without file uploads, 32M with them; keep upload_max_filesize below it. Also limit decoded request size, field count, multipart part count, header count and nesting depth at the web server / proxy — including requests without a usable Content-Length.
  • Container / cgroup memory limit as an availability boundary (ideally killing only the affected worker). Do not use RLIMIT_AS / RLIMIT_DATA — they can cause the vulnerable allocation failure.

CVE-2026-109619 (stale global state):

  • session.upload_progress.enabled=0 in php.ini, the FPM pool or server config (applies before request parsing), then restart every worker. Not via ini_set() or FPM .user.ini. Blocks the confirmed session paths only.
  • PHP 8.5: fatal_error_backtraces=0 and restart every worker (blocks the confirmed backtrace path only).
  • Remove invalid/deprecated per-request settings that emit diagnostics before initialization — hiding them (error_reporting, display_errors, @) does not help.
  • Fix attacker-reachable fatal errors and execution timeouts (callbacks, upload/import processing, cleanup).
DIY: Run the curl test script yourself

Want to run the exact same inert checks yourself directly from your terminal or CI? Below is the curl test script representing the 7 requests (1 GET + urlencoded & multipart across POST, PUT, and PATCH). It never sends upload-progress fields or file parts, so it is safe to run on authorized targets.

Bash / curl script


        

How to interpret the output:

  • X-Powered-By / Server header: Look for PHP version info (fixed releases: 8.2.35+, 8.3.36+, 8.4.27+, 8.5.12+).
  • Multipart 403 / 406 while urlencoded succeeds (200/302/405): Multipart is blocked by WAF/CDN/web server rule before PHP processes it (MITIGATED — UPDATE STILL NEEDED).
  • Multipart 200 / 3xx: Multipart request body reaches the application (ASSUMED VULNERABLE if unpatched).
  • All 405 Method Not Allowed: if the 405 responses carry no PHP signs (no PHPSESSID cookie, no X-Powered-By) the server refused before PHP (MITIGATED — UPDATE STILL NEEDED, or NO PHP DETECTED without any PHP indicators). A 405 that sets a PHP session cookie came from PHP itself, after it read the upload (ASSUMED VULNERABLE).