RCE via OOM corruption

Kurzinfo

Metadaten

  • Original (extern): Link oeffnen
  • Veroeffentlicht: 2026-10-21 13:34 UTC
  • Importiert: 2026-10-21 14:15 UTC
  • Quelle-ID: php_sec
  • uid_hash: 9e0929f5011569200ff2e69b7b032c18e2d4397df2e6232b98b6a3797c8a1ee6

Inhalt

Summary

PHP uses longjmp() for out-of-memory (OOM) errors to exit the current context and abort handling of the request. In some contexts, request memory is temporarily reachable before it is fully initialized. If any allocation fails at that point, PHP does not properly account for the early exit and leaves the request memory in an invalid state. The failed allocation does not need to be related to the invalid memory. The request shutdown procedure may then read or branch on it. Multiple OOM strategies can consistently trigger this condition and lead to remote code execution (RCE).

Vulnerability

OOM strategies

Several multipart parsing problems can let a request reach OOM while remaining within its apparent PHP limits:

  • A multipart request without a usable declared content length may pass the initial post_max_size check and continue supplying decoded body data.
  • A multipart part can contain an unrestricted number of headers. Representing these headers inside PHP can use substantially more memory than their wire representation, allowing a request within post_max_size to exhaust the normal memory_limit.
  • Empty file controls do not count towards max_file_uploads but still create the normal file metadata arrays. Nested field names multiply the generated array work.

OOM can also be reached in application-specific ways when attacker-controlled input causes a sufficiently large allocation or repeated memory use.

Susceptibility

Apache mod_php unconditionally invokes the request shutdown procedure, even when request startup has failed. During request startup, automatic body parsing can exhaust the configured memory limit and exit the request in a context where state is temporarily invalid. Shutdown then processes this invalid state. This happens entirely before any application-specific code begins execution.

FPM exits the child when request startup fails. This prevents consumption of the invalid state and removes the child from the pool. After normal startup, OOM may still be reached in a context failing to account for an early exit, with the invalid state being processed during request shutdown. Source analysis therefore supports FPM as a susceptible, though no complete FPM exploit has been demonstrated for this SAPI.

Source analysis indicates that FrankenPHP, analogous to Apache mod_php, calls the request shutdown procedure unconditionally, making it likely susceptible to application-independent attacks. LSAPI models FPM, with application-specific exploits being likely but unvalidated.

Mitigation

The patch removes longjmp() for OOM, avoiding an early exit out of contexts that do not properly account for it. It is replaced with a delayed, graceful soft OOM triggered at the next VM safe point, and an immediate hard OOM using _exit() if memory consumption reaches a second, higher threshold. The shutdown procedure will no longer see invalid state, and PHP's normal ability to limit memory consumption is retained.

[!WARNING] Updating to a PHP release containing the patch to this vulnerability is the only complete mitigation.

For installations that cannot update, setting and enforcing memory_limit=-1 administratively is the primary configuration mitigation. It removes the predictable per-request limit that enables the confirmed exploit with a controllable OOM. This is not a complete mitigation. If mmap() or another underlying allocation fails, PHP can still use longjmp() while incomplete request memory is reachable. Restart every PHP worker and confirm that no pool, directory or application setting restores a finite PHP memory limit.

Keep post_max_size conservative and independently enforce the decoded request size at the frontend. Reduce max_input_nesting_level, and bound the number of input variables, multipart parts, headers within each part and uploads. These controls reduce hard OOM and denial of service risk even after applying the patch, but do not replace updating. If the application does not use multipart form data, block such requests at the frontend before they reach PHP.

A container or cgroup memory limit (memory.max) may provide an alternative to PHP's own memory_limit with some limitations. It is not guaranteed to prevent allocation failure and is not a complete mitigation. For example, killing a container or cgroup can also kill the master and every worker, unless each worker has its own group. Killing one FPM child fails only its current requests and FPM's master replaces it quickly. Do not use RLIMIT_AS or RLIMIT_DATA, as these will cause mmap() to fail once the memory limit is reached, triggering the vulnerable longjmp() path.

Important: Make sure to also follow the remediation advice from the related report. https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp

Impact and reliability

The confirmed impact is unauthenticated remote code execution as the web worker account. Complete remote code execution was validated over HTTP against mod_php with default PHP input and memory limits and normal prefork configurations with multiple workers. Additional workers and unrelated traffic can increase the required number of attempts but do not remove the condition. Exploit portability and reliability depend on the PHP build, extensions, frontend behavior and allocator layout.

Verknuepfte CVEs

CVE-ID Severity (Quelle) CVSS (Quelle) Severity (CVE.org) CVSS (CVE.org) EPSS EPSS-Pctl Veroeffentlicht (CVE.org)

CVE-2026-109618

CRITICAL

Quellen-Details

Bezeichnung Name Kategorie Tags Zielgruppe Sprache Feed-URL
PHP Security (php/php-src GHSA)

php_sec

vendor_advisory php, runtime - de https://github.com/php/php-src/security/advisories