Skip to content
Exploit for Improperly Controlled Sequential Memory Allocation in Php

Exploit for Improperly Controlled Sequential Memory Allocation in Php

Sploitus • October 21, 2026

([GHSA-w8hw-w9fx-j79w](

"RCE via OOM corruption", CVSS v4.0 **9.2 Critical**, CWE-416) — one of the

two PHP core advisories fixed on **2026-10-21** in

> **Overview** — PHP handled out-of-memory errors with `longjmp()`. During

> the multipart (`rfc1867`) parsing window — which runs **before** the

> application and before full request initialization — request memory can be

> reachable but not fully initialized. An allocation failure there bails out

> and leaves invalid state; `php_request_shutdown()` still runs over it

> (mod_php always runs shutdown, even after a failed startup). Request-owned

> state published in worker globals survives the heap free and can be

> consumed by later requests on the same worker. The vendor-confirmed impact

| Pre-application OOM abort during request startup (stock limits: `memory_limit=128M`, `post_max_size=8M`) | **captured** | `evidence/02-trigger-oom-request-startup.txt` — `Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 69632 bytes) in Unknown on line 0` |

| Worker-pool degradation after aborts (DoS tier) | **captured** — 8/8 connection drops following aborts | `evidence/04-recorded-loop-receipts.txt` |

| Patched-build negative test (php-8.5.12, source-built) | **captured** — zero receipts, both PoC variants | `evidence/03-negative-patched-build.txt` |

| Cross-request UAF sanitizer receipt / memory disclosure / RCE | **documented, not reproduced here** | see reference links: vendor-confirmed RCE on stock WordPress/Drupal/Joomla (Wiz), both independent audits report full RCE requires per-build offsets + heap grooming |

Two independent peer-review passes were performed on this material (one

reject-and-fix iteration, one confirmation pass with zero blocking items).

poc/exploit_opt.py compact driver (seed -> arm -> fire)

poc/exploit_readable.py same chain, tutorial-grade

evidence/ captured lab transcripts (paths scrubbed)

Evidence transcripts are kept as captured; some `Command:` headers in them

reference the foundry's internal workspace layout (and an internal trigger

probe equivalent to the PoC's seed stage). The shipped `poc/` drivers

python3 poc/exploit_opt.py --url

python3 poc/exploit_readable.py --url

# negative check on a patched build must print no receipts (exit 2)

Knobs: `--key-mb` (progress-key size; grows the session file via aborted

seeds), `--seed-pad-mb` (padding so the seed aborts after the progress-entry

Expected on a vulnerable target: each aborted seed returns the OOM fatal

(`in Unknown on line 0` = fired during request startup, outside application

code), and `/tmp/sess_*` inside the container shows the persisted oversized

`upload_progress_*` keys. Expect worker-pool degradation after several

aborts — DoS-class corroboration, **not** a use-after-free receipt; the tool

prints each tier's receipt status separately and never claims an unreached

## Notes that matter if you study this bug

- The gate is at `main/rfc1867.c:697`: the `post_max_size` check compares

the **declared** `Content-Length` only. A chunked request declares no

length, so parsing continues until the real limiter — `memory_limit` —

- The widely repeated "cached `post_bytes_processed` zval pointer UAF"

(`php_session_rfc1867_callback`) is **not a UAF**: `Z_TRY_ADDREF` keeps the

progress array alive. Both public audits reached the same conclusion.

- Per-SAPI behavior differs: mod_php streams chunked bodies (bypass works);

the built-in server buffers them and derives their length (gate fires as a

- The fix (`31c0ea7d7f` "Avoid state corruption via bailout", php-src) is

shared with the sibling advisory CVE-2026-109619: OOM no longer

`longjmp()`s (delayed soft OOM + hard `_exit()` threshold), `ZEND_HAS_OOM()`

checks through the parser, part-header keep-list, pre-RINIT session decode

locked to `__PHP_Incomplete_Class`, early global resets.

1. **The complete fix is the updated release:** update to

2. `session.upload_progress.enabled=0` closes the session-lifecycle paths

(incomplete for other state families). On 8.5 also

`fatal_error_backtraces=0` removes the confirmed backtrace producer.

3. Do NOT use `RLIMIT_AS`/`RLIMIT_DATA` (mmap failure re-enters the

4. Frontend: block/rate-limit multipart POSTs where not needed; keep

`post_max_size` conservative; keep `fastcgi_request_buffering on` (nginx).

A self-contained `docker compose` lab ships in `lab/` (dedicated

network; ports published to loopback only):

docker compose build # vulnerable twin from a pinned image + ASAN and

# patched twins built from source (~25 min)

docker compose up -d # 8080=vuln(8.5.11) 8081=fixed(8.5.12) 8082=asan

curl # expect: app-ok 8.5.11, sapi=apache2handler

The compose file builds with `network: host` — on hosts whose resolver is

unroutable from bridge networks (AAAA-only DNS, no IPv6 route) that is

required; remove it if your host has clean bridge DNS.

- `Allowed memory size of ... exhausted ... in Unknown on line 0` with no

- Oversized/malformed `PHPSESSID` response cookies.

- Unexplained worker churn / connection drops after multipart bursts.

This material is for **authorized security research and defense work on

systems you own or are explicitly permitted to test**, in isolated lab

environments. The maintainers released fixes on the disclosure date; for

post-fix testing use a source build of the last vulnerable tag

(`php-8.5.11`). No warranty, see `LICENSE`.

- [GHSA-w8hw-w9fx-j79w — RCE via OOM corruption](

- [GHSA-6wmf-4rv5-p3rp — companion advisory (stale global state)](

- Wiz Research "PHP2Shell" blog; Calif + OpenAI disclosure blogs

- JackalSyn "php-up-2026" writeup (SAPI survival matrix, validation receipts)

Prepared with the b63 exploit-foundry tooling: advisory verification against

primary sources, a reproducible pinned-build lab, two PoC variants, captured

transcripts including a patched-build negative test, and two adversarial

review passes. Feedback and corrections welcome via issues.

Extracted Entities

Attack Types (1)

CWE Weaknesses (1)

Platforms (3)