← Research
Field Notes

PHP2Shell: Bespoke Exploits at Machine Speed

Two PHP runtime flaws can turn a web request into remote code execution. Our labs show what they do, how one AI-assisted session reached code execution in about four hours, and what to validate while you patch.

Conceptual illustration of a PHP processor chip on a dark circuit board, cracked open by a red fault line that streams across the board into a terminal window.

PHP2Shell exposes a serious weakness beneath applications that run on PHP: flaws in the runtime can allow an attacker to move from a web request to remote code execution when the necessary exploitation conditions are met. PHP released fixes on October 21, 2026, and Amazon and Cloudflare have reported exploitation attempts. For defenders, the immediate task is to update affected runtimes while checking whether deployed controls cover the relevant attack paths. [1, 3, 4, 5, 8]

The difficulty of building a working exploit is part of that response calculation. PHP2Shell requires adaptation to the target, and AI can help with the testing and debugging that adaptation demands. Across three complementary labs, ADCL's research team examined the failure mechanisms, compared vulnerable and patched runtimes, and reached code execution. One AI-assisted development session reached that outcome in about four hours. Together, the findings show why adaptation speed matters and what teams should validate as they respond.

Timeline titled Attempts began four days before the fix: 4 days from the first recorded attempt to the fixed releases. 1, October 17: Amazon records an exploitation attempt against its honeypots [8]. 2, October 20 to 21: CVE IDs circulate early, and PHP moves its October 22 release to October 21 [6]. 3, October 21: fixes released, and Amazon records more attempts [1, 8]. What it means: attempts in the wild are established; how many production systems were compromised is unknown. Cloudflare also reports attack traffic. Review telemetry from October 17.
Figure 1: Exploitation attempts were recorded four days before PHP shipped fixes on October 21.

Why the Response Window Already Matters

The urgency extends beyond lab demonstrations. Amazon reports an exploitation attempt against its MadPot honeypots on October 17, four days before public disclosure, followed by additional attempts on October 21. Cloudflare also reports attack traffic. These observations establish attempts in the wild, while leaving the number of successfully compromised production systems unknown. [5, 8] Figure 1 shows the window.

How PHP2Shell Reaches Beneath the Application

The two flaws involve how PHP manages memory when processing fails, or state carries over between requests. Because they sit in the runtime, their reach extends beneath individual application features. Successful exploitation still depends on the PHP build, configuration, and behavior of the deployed application. [2, 3, 4]

One flaw occurs when an allocation stops partway through, and cleanup treats partially initialized data as valid. The other is a use-after-free: a worker retains references to memory released by an earlier request, and a later request uses those references before PHP resets the state. An attacker who can influence that memory may turn a crash into information disclosure or code execution. Figure 2 identifies the two vulnerabilities and compares their failure paths. [3, 4]

Two flaws, and the releases that fix them. CVE-2026-109618 [3]: memory runs out mid-operation, before data is fully initialized; cleanup then treats that data as valid, corrupting memory. CVE-2026-109619 [4]: internal references still point to memory that was already released; a later request follows them before PHP resets state (use-after-free). Fixed in, by PHP branch: 8.5.12, 8.4.27 and 8.3.36 are fixed; 8.2.35, end of life December 31, 2026; 8.1 and older have no upstream fix, with backports for 7.4, 8.0 and 8.1. Both are rated critical. Exploitability depends on the PHP build, configuration, extensions and request handling. For vendor builds, confirm the vendor fix and package revision, not the version number [1].
Figure 2: The two flaws, and the PHP releases that fix them.

Creating those conditions takes work. The application's memory layout and request handling can change whether an exploit succeeds, which makes adaptation effort central to understanding the risk. AI-assisted iteration matters here because it can help researchers work through those deployment differences. [2, 3, 4]

PHP has released fixes for supported branches and exceptional minimal source backports for several older branches. Figure 2 lists the releases. Those backports address the immediate flaws without restoring ongoing support, so teams running older PHP installations should also plan migration. [1]

What the Team Established Across the Labs

The investigation combined tests designed to answer different parts of the same question: what happens when PHP retains request state after a memory-allocation failure? Localhost-only Apache/PHP containers covered WordPress and bare-PHP deployments across the 8.3 and 8.4 branches, alongside PHP 5.6.40. Instrumented mirrors and separate CLI debug builds let the team examine the underlying state transitions. Each test contributed to the collective result, from externally visible behavior to the memory operations behind it.

The service impact was clear in the bare-PHP comparison. PHP 8.4.26 timed out in all three follow-up cycles and finished with nine hung requests; PHP 8.4.27 returned HTTP 200 in all three checks and finished with none. Complementary WordPress tests also recorded persistent session locks on vulnerable 8.3 and 8.4 builds, while the patched controls continued answering probes. Earlier trigger responses alone had not captured that difference: both bare-PHP builds encountered out-of-memory errors, but their subsequent behavior diverged.

Lab results: the same checks, before and after the fix. PHP 8.4.26, vulnerable: all three follow-up checks timed out, 9 hung requests; logs showed out-of-memory errors, then every follow-up timed out. PHP 8.4.27, patched: all three follow-up checks returned HTTP 200, 0 hung requests; logs showed out-of-memory errors, and follow-ups answered normally. PHP 5.6.40, legacy: not reported by cycle; worker crashes and persistent session locks. Instrumented: on 8.3.35, session state survived a failed request and corrupted allocator bookkeeping; patched 8.3.36 cleared it. WordPress: vulnerable 8.3 and 8.4 builds recorded persistent session locks; patched builds kept answering probes.
Figure 3: Bare-PHP follow-up checks in the lab. PHP 8.4.26 timed out in all three cycles with nine hung requests; PHP 8.4.27 returned HTTP 200 in all three with none.

Instrumented testing helped explain those symptoms. On PHP 8.3.35, the team traced session state that survived a failed request and was consumed by a later request. In a captured crash, that stale state corrupted allocator bookkeeping, causing a worker to fail during a subsequent allocation. The patched PHP 8.3.36 control cleared the observed stale state and completed the corresponding crash-test sweeps without a crash. Legacy PHP 5.6.40 tests also recorded worker crashes and persistent session locks.

The combined investigation also established that data from another session remained in worker memory. In an instrumented PHP 8.3.35 lab, researchers recovered a planted test secret from a captured worker heap dump. This debugger-assisted collection demonstrated exposure of sensitive data within the worker's memory image; it was not a demonstration of remote extraction of that secret over HTTP. Alongside the crashes and session locks, the recovery shows consequences extending beyond a failed request.

Taken together, the tests connect observable service disruption with the underlying memory lifecycle and show how patched controls behaved under the tested conditions. Applying those findings to production still requires checking the active runtime and vendor patch status, since configuration differences or a blocked request can change what a test reveals. [1]

How AI Helped With the Adaptation Work

Those collective findings explain the impact of the flaws. Reaching code execution adds a further question: how much work does it take to adapt them to a particular application? Wiz describes using frontier models to develop and refine PHP2Shell exploits across applications, with repeated testing and debugging to overcome deployment differences. [2]

In one approximately four-hour session, our team used an open-weight model to build lab code, analyze PHP's behavior, and execute a command as the web server user, www-data, on an instrumented PHP 8.3.35 target. The command wrote its identity output to a file on the target filesystem. The resulting file contained the www-data user and group identifiers and was owned by that account, demonstrating command execution and filesystem write access under the worker's privileges. Operators supplied prompts and approved design decisions, while the model authored the lab code and developed the exploit structures. The debugger supplied memory-state information for the final stage. Open weights allowed the model to be used outside a single proprietary service, subject to its license and hardware requirements.

The wider team investigation also included a separate HTTP-only chain that reached execution as www-data. Together, the instrumented and HTTP-only work established code execution through complementary methods. The four-hour interval describes the instrumented development session, rather than the elapsed time for the entire multi-lab investigation.

That result gives a concrete example of AI-supported, target-specific exploit development in a controlled environment. The time required will vary with the deployment and testing conditions.

One lab session: what it shows and what it does not. What it shows: about 4 hours, one instrumented development session; command execution as www-data on an instrumented PHP 8.3.35 target; a file holding the www-data user and group IDs; an open-weight model wrote the lab code, and operators approved the design. What it does not show: the elapsed time of the whole multi-lab investigation; a hands-off run, since a debugger supplied memory state for the final stage; a portable exploit, since it did not work unchanged on another tested setup. Evidence: ADCL lab observation on an instrumented target. A separate HTTP-only chain in the wider investigation also reached execution as www-data.
Figure 4: What the roughly four-hour instrumented session shows, and what it does not.

Why the Target Still Matters

AI assistance does not remove the deployment details that make this work difficult. PHP version, configuration, extensions, application behavior and memory layout all influence adaptation. PHP's stale-state advisory, for example, describes conditions in which one request leaves state that another consumes. [2, 4] Our lab exploit worked on its intended application and did not transfer unchanged to another tested setup. That experience shows why target-specific testing remains necessary, even though some exploit techniques may carry across applications.

The iteration needed to find a working path may also give defenders opportunities to detect it. Wiz highlights memory-limit errors, bursts of HTTP 500 responses, malformed session cookies and unexpected worker churn patterns worth investigating. [2] Those signals are useful leads, although PHP notes that affected lifecycle paths can occur without a predictable log entry. [4] Monitoring can help surface attempts while remediation proceeds; a quiet log alone cannot establish that the runtime is safe.

What the WAF Can Cover

While teams update PHP, a web application firewall can reduce exposure to known request patterns. Cloudflare reports deploying PHP2Shell protections before public disclosure, including detection that combines request and response signals. AWS documents managed and custom rules. Their effectiveness depends on how traffic reaches the application and how the deployed rules inspect and handle it. [5, 9]

Those deployment details become especially important when an attack depends on multipart parsing and memory behavior.

AWS WAF's body inspection window is fixed at 8 KB for Application Load Balancer. CloudFront defaults to 16 KB and supports higher limits. A payload beyond the inspection window may escape a body-pattern rule, while size rules, oversize handling or other controls can still block the request. An inspection limit by itself is not evidence of a successful bypass. [9]

Request size also gives an incomplete picture of the work PHP performs. Multipart processing can consume much more memory than the request's wire size suggests, so a body-size cap cannot cover every case. [3, 9] Routing introduces a separate exposure: a publicly reachable origin may allow requests to avoid the intended edge controls altogether.

To determine what protection is in place, check the rule versions, actions, exceptions, and traffic paths. A Count or log-only action records matches without blocking them. Validate intended blocking after tuning rules for legitimate application traffic. [9]

Cloudflare has observed attackers varying payloads in attempts to bypass its protections, which reinforces the need to keep rules current as the runtime update proceeds. The reported variations establish attempted adaptation, not that every attempt succeeded. [5]

A useful validation therefore follows traffic through the deployed controls to the application. Blocking a test request confirms that the relevant control matched it. Closing the underlying memory-safety flaws still requires the PHP update.

Where a WAF falls short on PHP2Shell [9]. Body inspection window: Application Load Balancer, 8 KB, fixed; CloudFront, 16 KB default, higher limits supported. Past the window: a payload beyond the 8 KB or 16 KB window can escape a body-pattern rule; size rules can still block it [9]. Small request, big memory: multipart parsing can use far more memory than the request size suggests; a size cap alone does not cover it [3, 9]. Count is not block: a Count or log-only action records a match without blocking; check rule versions, actions and exceptions [9]. Around the edge: a publicly reachable origin lets requests skip edge controls; restrict it to approved ingress. Patch first: a WAF buys time, not a fix. Update PHP.
Figure 5: AWS WAF body inspection windows, and four ways a WAF can fall short on PHP2Shell.

Turning the Findings Into a Response

The immediate priority is to update the runtime that serves the application, then verify the result. The lab comparison makes that distinction tangible: patch status, traffic controls and observed application behavior each answer a different operational question. Figure 6 summarizes the response as three parts: patch, contain and hunt.

  1. Update the PHP runtime behind every web pool, container image, and hosting service. Redeploy fixed images or packages and replace or restart affected workers as appropriate. Confirm the runtime serving requests; restarting a container with the old image does not install the fix. [1]
  2. If an immediate update is unavailable, apply relevant PHP advisory mitigations administratively in php.ini or pool configuration and restart workers. Match each setting to its documented scope; no configuration-only workaround completely addresses both flaws. [3, 4]
  3. Consider blocking multipart traffic where the application does not require it, after checking legitimate form and uploading workflows. [9]
  4. Review WAF inspection limits, oversize handling, size controls and rule actions. Increase inspection limits where supported and appropriate; the Application Load Balancer body limit is fixed. Confirm intended blocking after validation. [9]
  5. Restrict access to the origin to approved ingress paths and verify that direct requests cannot bypass the intended edge controls.
  6. Correlate multipart requests, memory-limit errors, HTTP 500 bursts, malformed session cookies and worker churn with host and proxy telemetry. Treat these as investigation leads, not proof of compromise. [2]
  7. Review available telemetry from at least October 17, the earliest attempt Amazon reports, and extend the review when local evidence warrants it. [8]
Response plan: patch, contain, hunt. 1 Patch: update the PHP runtime behind every web pool, container image and hosting service, and confirm the version actually serving requests [1]. 2 Contain: cannot update yet? Apply the advisory mitigations and restart workers; block unneeded multipart traffic, review WAF limits and restrict the origin [3, 4, 9]. 3 Hunt: review telemetry from at least October 17 for memory-limit errors, HTTP 500 bursts, malformed session cookies and worker churn; these are leads, not proof [2, 8]. Track each system separately: potentially affected, temporarily mitigated, patched, retest complete. Record any blocked request or unsuitable method as limited validation. Updating PHP does not show an earlier intrusion was removed.
Figure 6: Patch, contain and hunt, with four statuses to track separately for each system.

One configuration change deserves particular care. Disabling session.upload_progress.enabled addresses the demonstrated early session lifecycle path of CVE-2026-109619 but leaves other lifecycle paths and CVE-2026-109618 incompletely covered. PHP recommends considering keeping the feature disabled after patching if the application does not need it. Apply the setting administratively and restart workers, while continuing toward the runtime update that provides the complete fix. [3, 4]

Incident investigation remains a parallel responsibility: updating PHP closes the weakness but does not establish that an earlier intrusion has been removed.

Where ThreatWell Supports That Work

That combination of discovery, testing, and follow-through is where ThreatWell can support the response. ThreatWell Command connects reconnaissance, assessment and authorized exploitation testing against running systems, while ThreatWell Codex adds source and dependency analysis. Together, those capabilities help teams investigate exposure and carry findings into remediation within the deployment and engagement scope. [7] In this investigation, the team used ThreatWell MCP queries to retrieve vulnerability records and exploit intelligence alongside public advisories and PHP source code. That provided research context for the AI-assisted work; the exploit-development outcome belongs to the research team's combined lab workflow.

The team's findings give defenders a reason to treat exploit adaptation as a time-sensitive part of the response. AI-assisted development reached code execution within about four hours in one controlled session, while complementary tests established service disruption, retained sensitive data in worker memory, and different behavior after patching. The practical response is to bring those lessons together: update the PHP runtime, validate the deployed application, and investigate signs of attempts while that work is underway.

Sources

Public vulnerability and mitigation references were reviewed October 22–23, 2026. Lab findings reflect the ThreatWell research team's combined investigation across three complementary labs. The approximately four-hour timeframe refers to one AI-assisted, instrumented development session.

  1. PHP. Security advisory and October 21 security releases.
  2. Wiz Research. PHP2Shell research disclosure.
  3. PHP security advisory. RCE via OOM corruption (CVE-2026-109618).
  4. PHP security advisory. RCE via stale global state (CVE-2026-109619).
  5. Cloudflare. Cloudflare deploys protections against php2shell vulnerability.
  6. The PHP Foundation. Today's PHP Security Release and How We're Strengthening PHP Security.
  7. ADCL. ThreatWell platform.
  8. Amazon Threat Intelligence. PHP2Shell exploitation attempts observed in MadPot.
  9. AWS. Using AWS WAF to apply mitigations for PHP2Shell RCE vulnerabilities.

Get the research
before the attackers do.

We publish what we find so defenders can fix it first. Want this applied to your environment? Talk to us about ThreatWell.