{
  "id": "php2shell",
  "url": "https://ohshit.app/incidents/php2shell/",
  "title": "PHP2Shell: two critical PHP core RCEs leak a day before the patch, and nearly every PHP back to 5.4 is in the bowl",
  "level": 5,
  "level_name": "shitstorm",
  "date": "2026-10-21",
  "date_is_approximate": false,
  "updated": null,
  "tags": [
    "PHP",
    "RCE",
    "leaked early"
  ],
  "ecosystems": [
    "php"
  ],
  "summary": "CVE-2026-109618 and CVE-2026-109619 (both CVSS 9.2) give remote code execution in PHP itself. A proof-of-concept video leaked the evening before release, so the patch and the exploit arrived together.",
  "splash": "PHP-FPM, mod_php, php-cgi, FrankenPHP, LiteSpeed: nearly every PHP back to 5.4",
  "wipe": "Upgrade to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35. Disabling session.upload_progress only blunts one of the two bugs",
  "in_the_wild": "disputed",
  "source_exception": null,
  "cves": [
    {
      "id": "CVE-2026-109618",
      "score": 9.2,
      "name": "Half-built request on out-of-memory",
      "description": "If PHP runs out of memory at the wrong moment, it can bail out while internal request data is only partly initialised. This path does not need session.upload_progress.",
      "plain": "the toilet gets installed with only half its bolts, and someone sits down anyway."
    },
    {
      "id": "CVE-2026-109619",
      "score": 9.2,
      "name": "Stale request state used after free",
      "description": "Request-owned global state survives after its memory is released, and a later request on the same worker uses it. session.upload_progress is the confirmed trigger.",
      "plain": "you flushed it, but it came back up in the next person's stall, and now it runs your server."
    }
  ],
  "fixed": [
    {
      "product": "PHP 8.5",
      "branch": "8.5",
      "version": "8.5.12",
      "status": "Supported, patched"
    },
    {
      "product": "PHP 8.4",
      "branch": "8.4",
      "version": "8.4.27",
      "status": "Supported, patched"
    },
    {
      "product": "PHP 8.3",
      "branch": "8.3",
      "version": "8.3.36",
      "status": "Security fixes only, patched"
    },
    {
      "product": "PHP 8.2",
      "branch": "8.2",
      "version": "8.2.35",
      "status": "Security fixes only, patched. EOL Dec 31, 2026"
    },
    {
      "product": "PHP 8.1 and older",
      "version": "none",
      "status": "End of life. Distro / LTS vendors and source backports for 7.4–8.1 only"
    }
  ],
  "checklist": [
    {
      "title": "Find every PHP runtime",
      "hint": "Servers, Docker base images, CI runners, that forgotten WordPress box"
    },
    {
      "title": "Upgrade to a fixed version",
      "hint": "8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 or later. 8.1 and older need a distro or LTS build"
    },
    {
      "title": "Double-check with OpenAI's php2shell-checker",
      "hint": "Point it at a URL or run it on the box. UNKNOWN means it couldn't tell, not that you're clean"
    },
    {
      "title": "Rebuild and redeploy images",
      "hint": "A patched host does nothing for an old container"
    },
    {
      "title": "Disable session.upload_progress where you can't patch yet",
      "hint": "Partial mitigation for CVE-2026-109619 only"
    },
    {
      "title": "Hunt for web shells",
      "hint": "New .php files in upload and cache dirs since Oct 20"
    },
    {
      "title": "Rotate secrets the app could read",
      "hint": "DB passwords, API keys in .env, session signing keys"
    }
  ],
  "sources": [
    {
      "name": "php.net news",
      "url": "https://www.php.net/",
      "says": "Advance notice Oct 20, releases Oct 21. Updating is the only complete fix",
      "primary": true
    },
    {
      "name": "Patchstack",
      "url": "https://patchstack.com/articles/php-major-vulnerability-alert-10-2026/",
      "says": "Headline says attacks are ongoing; later telemetry shows probing, no confirmed breach",
      "primary": true
    },
    {
      "name": "Sophos",
      "url": "https://www.sophos.com/en-us/blog/proof-of-concept-exploit-released-for-php-vulnerabilities-109618-109619",
      "says": "PoC public; no in-the-wild exploitation reported; PoC claims not verified",
      "primary": true
    },
    {
      "name": "The Hacker News",
      "url": "https://thehackernews.com/2026/10/php-issues-emergency-patches-for-two.html",
      "says": "Credits Wiz Research, Calif and OpenAI Codex Security; Gemini team helped on the fix",
      "primary": false
    },
    {
      "name": "Huntress",
      "url": "https://www.huntress.com/blog/php2shell-leaked-critical-php-vulnerabilities",
      "says": "Coined “php2shell”; leaked before the release",
      "primary": false
    },
    {
      "name": "JFrog Security Research",
      "url": "https://research.jfrog.com/post/php2shell-all-you-need-to-know-about-cve-2026-109618-and-cve-2026-109619/",
      "says": "Technical deep-dive on both CVEs",
      "primary": false
    },
    {
      "name": "OpenAI php2shell-checker",
      "url": "https://github.com/openai/php2shell-checker",
      "says": "Version check by URL headers or local php -v; same fixed versions as php.net, misses distro backports",
      "primary": false
    }
  ],
  "headline": "PHP2Shell: the patch and the exploit flushed at the same time",
  "one_liner": "Make PHP run out of memory at exactly the wrong moment, or poke a worker that still holds a previous request's freed state (session.upload_progress is the confirmed way in), and the next thing PHP executes is your bytes.",
  "in_the_wild_note": "Attempts seen by watchTowr and Cloudflare; no confirmed breach yet",
  "mitigation": {
    "file": "php.ini",
    "code": "; PHP2Shell interim hardening (partial!)\n; blocks the confirmed CVE-2026-109619 session path only\nsession.upload_progress.enabled = Off\n",
    "note": "Then reload PHP-FPM / Apache. php.net is clear that upgrading is the only complete fix: this does nothing for CVE-2026-109618. Capping request body size at your proxy also raises the bar."
  },
  "timeline": [
    {
      "date": "Oct 20, 2026",
      "title": "The details escape the bathroom",
      "body": "A Hacker News post says disclosure is due Oct 22. Around 20:00 UTC Calif accidentally publishes a proof-of-concept video. PHP posts an advance notice the same day."
    },
    {
      "date": "Oct 21, 03:02 UTC",
      "title": "Cloudflare switches on default WAF rules"
    },
    {
      "date": "Oct 21, 07:34 UTC",
      "title": "Patchstack hosting partners report exploitation incidents",
      "body": "Its 13:57 UTC telemetry update shows probing, with no hard evidence of breaches."
    },
    {
      "date": "Oct 21, 14:00 UTC",
      "title": "PHP ships 8.5.12, 8.4.27, 8.3.36 and 8.2.35",
      "body": "Linux distributions and LTS vendors got the patches in advance."
    },
    {
      "date": "Oct 21, 14:19 UTC",
      "title": "watchTowr sees active exploitation attempts",
      "body": "watchTowr also reproduces CVE-2026-109618. Sophos says no in-the-wild exploitation has been reported."
    }
  ],
  "body_markdown": "Two bugs in PHP's own engine, not in some framework or plugin. **Nearly every PHP release back to 5.4 is\naffected** by at least one of them. Apache `mod_php` is the highest-risk setup, but PHP-FPM, `php-cgi`,\nFrankenPHP and LiteSpeed are all in scope.\n\nThe disclosure was planned for October 22. On the evening of October 20 a proof-of-concept video from\nCalif, one of the reporting teams, went public by accident, and PHP pushed its releases out on October 21\nat 14:00 UTC. So for once, defenders and attackers started the race at the same time.\n\n**Is it exploited?** It depends on whom you ask. Patchstack's partners and watchTowr saw real attack\nattempts within hours. Cloudflare saw early attempts too. Sophos had no reports of exploitation, and\nnobody had confirmed a successful break-in at the time of writing. We grade by the worst credible case:\npublic PoC + default configuration + basically the whole web = **L5**.\n\n### Common misreading\n\nTurning off `session.upload_progress` is **not** a fix. It only cuts the confirmed path to\nCVE-2026-109619. The out-of-memory bug, CVE-2026-109618, does not need it."
}