← Back to blog
Blog Detail

PHP2Shell CVE-2026-109618 and CVE-2026-109619: Testing Multipart Exposure and Proving What the WAF Misses

PHP2Shell is two unauthenticated RCEs in PHP's multipart parsing path. Test whether a multipart POST reaches the runtime, then prove whether your patch-window WAF rule actually matches the traffic.

Trusteed Team
Trusteed Editorial
Written On
Oct 22, 2026
Category
Research
Read Time
9 min read
  • PHP2Shell
  • CVE-2026-109618
  • CVE-2026-109619
  • PHP
  • AWS WAF
  • Vulnerability Validation
  • Trusteed
PHP2Shell CVE-2026-109618 and CVE-2026-109619: Testing Multipart Exposure and Proving What the WAF Misses

PHP2Shell CVE-2026-109618 and CVE-2026-109619: Testing Multipart Exposure and Proving What the WAF Misses

TL;DR

PHP2Shell is two unauthenticated remote code execution bugs in PHP's multipart/form-data request parsing — CVE-2026-109618 (out-of-memory corruption) and CVE-2026-109619 (stale global state reused by a later request on the same worker), both rated 9.2 under CVSS v4.0 and fixed in PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35. A scanner line that says "PHP 8.3.31 detected" is a version guess, not a finding. The testable question is whether an unauthenticated multipart POST reaches the PHP runtime at all — and, if you deployed edge rules during the patch window, whether those rules match the traffic you believe they match. The evidence is a response differential: the same request with and without the trigger field, against a build you can confirm.

What this is

PHP2Shell is a pre-application vulnerability class. Both bugs sit in PHP's request parsing path, which runs before your router, your auth middleware, your framework, and your controllers. That changes the exposure question. You are not asking "is there an upload feature?" You are asking "does an unauthenticated client get a multipart body into a PHP worker process?" A comment form, a contact endpoint, a JSON API that tolerates a multipart/form-data content type, or a framework that parses the body on every POST is enough surface.

The second thing you are testing is your own compensating control. Edge rules deployed as a patch-window mitigation are a hypothesis about attacker traffic. Until you send deliberate traffic and watch the rule metric increment, you have a configuration, not a control.

Why it matters

Three things fail at once during a disclosure like this:

  • Inventory. PHP is everywhere and rarely bills itself as PHP: container base images, shared hosting, vendor appliances, a forgotten 8.2 branch on a marketing site behind a CDN. You cannot schedule a patch for a build you have not located.
  • The mitigation. A rule that matches multipart/form-data, a size cap, or a field name is a filter on a syntax the attacker controls. Header amplification, for instance, stays under a body-size cap while costing far more memory inside PHP than its wire size suggests.
  • The assumption. "We have no file uploads, so we're not exposed" is the exact reasoning that leaves a multipart/form-data POST landing in the parser.

Patching is the only complete fix. The gap between disclosure and a tested build is where the real risk sits, and that gap is what you can measure.

How it works

CVE-2026-109618 corrupts memory when PHP runs out of memory mid-request while internal request data is only partially initialized. CVE-2026-109619 lets one request leave stale global state behind that a later request on the same reused worker process consumes. The second bug is stateful: an attacker's requests need to land on the same worker to chain, which shapes both exploitation and why a rate-based rule helps at the margin.

Both entry points are multipart parsing. The AWS Security Blog's published coverage table for these CVEs is the most useful public artifact for a test plan, because it says where edge inspection stops:

  • The session upload progress field (PHP_SESSION_UPLOAD_PROGRESS) — blockable at the edge with a targeted rule.
  • Blocking multipart/form-data outright — viable only if the application has no legitimate multipart uploads.
  • Oversized bodies — a request body cap helps, but header amplification stays inside the cap, and the WAF does not parse individual part headers.
  • Worker reuse — rate-based rules blunt volume; they do not remove the path.
  • fatal_error_backtraces state and invalid/deprecated INI diagnostic paths — server-side settings with no edge coverage at all.

Affected versions, per the PHP advisories (GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp): everything before 8.5.12, 8.4.27, 8.3.36, and 8.2.35 in those respective branches is in scope.

The validation shape is three probes against one host: a benign multipart POST, the same POST with the session upload progress field added, and a body crafted under the inspection limit with many small part headers. Compare status codes, response bodies, and timing. Then repeat on a replica of the same build without the WAF to see what the control was actually masking.

Detection and response

Trusteed insight card with three multipart POST probes against one host — baseline 200, PHP_SESSION_UPLOAD_PROGRESS 403 with rule match, and a header-fragmented body returning 200 as a WAF rule miss.

On the defender side, the telemetry that matters is per-rule, not aggregate:

  • WAF logs and CloudWatch rule metrics. Is each rule in Count or Block? Which sampled requests matched? Did any legitimate upload or large JSON POST get caught?
  • Body inspection limits. Per AWS documentation, the limit is fixed at 8 KB on Application Load Balancer and AppSync; on CloudFront and API Gateway the default is 16 KB and can be raised to 32, 48, or 64 KB via AssociationConfig. A body-size rule can only enforce a cap up to the inspected size — a size rule configured above the limit is decorative.
  • PHP-FPM and web server logs. Worker OOM kills, segfaults, fatal errors, and worker respawn bursts clustered on one client or one URL.
  • Access logs. Multipart POSTs carrying PHP_SESSION_UPLOAD_PROGRESS, and 500/502 clusters from a single source.
  • IPS coverage. Cisco Talos published Snort signatures 67359 and 67360 for these bugs; confirm your signature set is current and alerting, not just installed.

The check a defender actually runs: send the three probe requests yourself, expect a 403 and a matching rule metric, and treat a 200 as a rule that does not match. Then verify the same probe on the origin or a replica to see what the edge was hiding.

What to do

  1. Fingerprint the build, not the banner. X-Powered-By is often stripped. Collect what the server does disclose — cookie names such as PHPSESSID, error page shapes, leftover phpinfo output, static asset hashes — then confirm the real version from the inside: composer.lock, base image digest, or the package database. The external fingerprint ranks hosts; it does not prove a version.
  2. Probe reachability. Send a well-formed, harmless multipart POST to endpoints that accept POST. Record status code, response shape, and whether the body was parsed.
  3. Add the trigger field. Repeat the request with PHP_SESSION_UPLOAD_PROGRESS in the body. A 403 means your edge rule matches; a 200 means it does not, and the path is still live.
  4. Test the header-amplification shape. Build a multipart body under the inspection limit containing many small part headers. If it is accepted, the size cap is not a control for that path — record it as a gap, not a pass.
  5. Test worker reuse with coordination. Hit the same endpoint repeatedly over a keep-alive connection and watch for latency shifts, 500s, or worker restarts. This is a burst test: get the owner's approval and keep it short.
  6. Prove exploitability on a replica. The same build, in staging, without the WAF, with a canary file or callback. Anything short of that is a theoretical exposure — label the finding accordingly.
  7. Re-run the probes after patching. The trigger field will still be accepted, because it is normal PHP. The regression signal is the confirmed build plus a fresh reachability map, so the next parsing CVE already has a blast-radius answer.

FAQ

Does blocking multipart/form-data fix PHP2Shell? No. It removes one attack path for applications with no legitimate multipart uploads, and it removes the session-upload-progress trigger. It does not touch the server-side paths, and it will break uploads if you have any.

Is a WAF rule an acceptable fix during the patch window? It is a mitigating control only. The PHP advisories are explicit that upgrading to a patched release is the complete mitigation. Deploy rules, keep them in Count mode until the metrics are clean, then Block — and remove or consciously retain them afterward.

How do I prove my rule actually works? Send three deliberate requests: a benign multipart POST, an oversized body, and a request carrying PHP_SESSION_UPLOAD_PROGRESS. Expect a 403 with the matching rule metric for the paths you intended to cover, and confirm legitimate traffic is untouched.

Do I need an upload feature to be exposed? No. You need PHP to parse a multipart body before your application code runs, which is why "we don't accept files" is not an answer.

Why does CVE-2026-109619 care about the same worker? Because the primitive is stale state left behind by one request and consumed by another on the same reused process. Load balancers and worker pools spread requests; that friction is a mitigation factor, not a fix.

Can I run these probes against production? The reachability and trigger-field probes are cheap and non-destructive. The worker-reuse burst is not — schedule it, keep it short, and do the exploitability proof on a replica.

Where this fits in a program

The reachability test is only as good as the host list behind it. Attack surface inventory that fingerprints the runtime on each domain and service turns "we should check PHP versions" into a ranked worklist; a validation gate keeps an unconfirmed banner out of the SOC queue until someone proves reachability. That is the difference between a scanner signal and a finding a second researcher can reproduce. Trusteed covers both steps; the probes above are yours to run.

Sources

Join Our Newsletter

Trusteed keeps you informed: emerging risks, platform updates, and practical guides for faster defense.