How many servers are one malformed upload away from leaking your secrets?
PHP2Shell is a pair of critical flaws that let unauthenticated attackers run code remotely on PHP installations serving web requests. Because PHP runs roughly 70% of the world’s websites and the bugs fire before any application code executes, even a fully patched WordPress, Drupal, or Joomla site is exposed until the PHP underneath is updated, and attackers are probing for it.
Calif, a security research firm working under OpenAI’s Patch the Planet initiative, found the bugs first on August 1 and reported them to PHP on August 11. Wiz Research found them separately.
What we know so far #
- Two critical flaws in PHP itself. CVE-2026-109618 and CVE-2026-109619 sit in the core engine, so even secure application code can’t protect a vulnerable server. An unauthenticated remote attacker can read a PHP worker’s memory (passwords, tokens, API keys) and, in some cases, run code on the server.
- Wide reach. Every PHP version back to 5.4 is affected, across PHP-FPM, Apache modphp, php-cgi, FrankenPHP andLiteSpeed, with mod php carrying the greatest risk.
- Proven on real platforms. Remote code execution was demonstrated against the latest WordPress, Drupal and Joomla container images. Even a "Hello World" PHP app can be vulnerable.
- A****fix is out, but the leak came first. Patched releases shipped on October 21: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older have no official release.
Why this matters #
Most teams will log this as two PHP bugs, now patched. The exposure behind it is bigger than that.
- The flaws sit beneath the application. CVE-2026-109618 and CVE-2026-109619 live in the PHP runtime, so the framework, CMS, or custom code on top is irrelevant. Exploitation can occur before any application code executes, which means app-level logging may capture little or nothing.
- No application mistake is required. The attack doesn’t depend on a vulnerable plugin, a weak login flow, or sloppy session handling. A site with clean code can still be exposed if the PHP underneath is not updated.
- It can be abused unauthenticated. An attacker needs no account, no password and no foothold, just the ability to send a request to your server.
- The cost of building an exploit has dropped. The researchers report that AI models compressed what used to take months of specialist work into days. Decade-old bug classes once considered impractical to weaponize are now within reach, and attackers have access to the same tooling.
With PHP running a vast portion of the web, from WordPress and Drupal to the internal tool nobody has touched in years, the question isn’t whether you run it. It’s where, and whether, you can find every instance.
Actions to take this week #
Detection
- Look for the setup phase. Malformed or unusual multipart upload requests, followed by memory-limit errors or bursts of HTTP 500 responses, are the pattern to hunt for.
- Inspect outbound cookies. An oversized or malformed PHPSESSID in a response can indicate that process memory is leaking back to the client.
- Flag process creation during upload handling. A PHP worker should never spawn a child process while it is still parsing an upload, before application code has run. Treat it as a high-confidence signal.
These signals guide an investigation. They do not replace patching.
Remediation
- Inventory every PHP install. Go beyond the obvious web apps. Bundled software, appliances, and forgotten internal tools all count.
- Patch internet-facing systems first. Move to PHP 8.5.12, 8.4.27, 8.3.36, or 8.2.35, depending on your branch.
- Rotate secrets on exposed servers. If an attacker could have read worker memory before you patched, assume the credentials, tokens, and API keys resident in that memory are compromised.
Want to know how a single out-of-memory crash turns into code execution? Keep reading.
A deep dive on what we know about PHP2Shell #
The PHP disclosure describes four bugs, classified as two CVEs. Together, they are the PHP2Shell. The first three share a common "pre-phase" that sets them up for success and essentially allows the final target of the desired RCE (remote code execution). The fourth is a more internal process, and how it was abused was not disclosed.
To see how they affect the server, we first need a few concepts.
PHP who? A short glossary
- PHP web server worker. A process that handles an HTTP request and is reused for later requests rather than restarted each time.
- Multipart request parsing. PHP reading an incoming multipart/form-data request (a file upload) and breaking it into labeled parts. This starts very early in the request.
- Session upload-progress handling. A PHP feature that tracks a file upload's progress so a page can show a progress bar. It runs while the server is parsing the multipart request.
- Session. PHP's way to remember a user across requests (the PHPSESSID cookie).
- Memory limit. The maximum memory a single request may use.
- Engine-global pointers. Internal bookkeeping variables the PHP engine uses to track global execution state. Three matter here:
- PS(id): the session ID.
- BG(unserialize): the unserializer state (the state of rebuilding the original array or object from a serialized string).
- EG(last_fatal_error_backtrace): stores information about the last error.
- Worker cleanup. A normal teardown process in PHP is supposed to run between requests on a reused worker, resetting the engine-global pointers so the next request starts clean. The bug chain exists because out-of-memory fatal errors abort the requestbefore this cleanup runs, leaving those pointers stale.
- OPcache. Shared memory holding precompiled script bytecode that all workers can read, which removes the need to re-read and recompile the same PHP file.
Now that we have the vocabulary, let's move to the part that makes it all possible.
The pre-phase #
The core concept being abused is a use-after-free (UAF): memory is freed, but a pointer to it is still kept and later used. If an attacker gets new data placed into that freed memory, PHP treats the attacker's bytes as its own trusted structure.
The attacker sends a crafted multipart upload that causes PHP to run out of memory during session upload-progress handling early in the request. The request ends unexpectedly, worker cleanup is skipped, and stale pointers remain. That can lead to memory disclosure or corruption.
Attacker flow:
- Craft an arming request. The attacker sends a multipart/form-data upload with session upload-progress data sized to run out of memory while still parsing.
- Early, pre-app parsing. Upload-progress handling runs before normal PHP startup finishes, so the engine-global pointers are set up early.
- Out-of-memory fatal error. The request exceeds memory_limit; PHP aborts and frees the request heap.
- Cleanup is skipped. The pointers are never reset.
- The worker survives and is reused. The same worker handles the next request, still holding the stale pointers.
- Memory usage. The attacker's data reclaims one of the freed allocations (each pointer has its own separate allocation).
This is the setup the first three bugs depend on.
Bug 1: Remote process-memory disclosure #
After the pre-phase, another multipart request on the same worker still trusts the freed allocation of PS(id). PHP reads the reclaimed bytes as a live session ID and URL-encodes them into the PHPSESSID response cookie. An attacker can simply read the cookie to get leaked worker's memory. That lets them defeat address uncertainty, which is what makes the next step toward RCE practical.
Bug 2: Unserializer use-after-free #
Here, the freed allocation of BG (unserialize) is trusted to trigger memory corruption. PHP keeps "unserializing" using attacker-reclaimed memory as if it were still valid, becoming a memory-corruption primitive. Combined with Bug 1's leak, this bug exploited address uncertainty to achieve an unauthenticated RCE and was demonstrated on WordPress, Drupal, and Joomla.
Bug 3: Fatal-error backtrace use-after-free #
Another pointer abuse of the EG(last_fatal_error_backtrace). If the same worker sends out a diagnostic event (any subsequent error or warning) after the failed cleanup it can access the freed pointer before the reinitialization of the state. PHP will update or destroy pointer backtrace and will follow the attacker-reclaimed memory. This use-after-free could be developed into memory corruption that can lead to RCE.
Bug 4: OPcache type confusion (a separate flow, across workers) #
The Wiz disclosure does not describe specific requests or steps for this bug, only an internal mechanism flaw. So, in short:
- Shared compiled-code cache. OPcache stores precompiled bytecode in shared memory so every worker can reuse it instead of recompiling (php.net: "removes the need for PHP to load and parse scripts on each request").
- Two trackers. A process-local tracker (CG(map_ptr_last)) and a shared tracker (ZCSG(map_ptr_last)) both track how far the shared memory has been filled.
- Allocation failure mid-update. In the window between the two trackers being updated, an allocation failure can leave the shared tracker out of sync with what was written.
- Cross-worker reuse. Wiz says this can allow a different worker to reuse that memory slot, it will resolve to a pointer of the wrong type. This causes a type confusion and corrupts the shared OPcache state, which was later leveraged to an RCE. Exactly how and when this happens is not spelled out, so treat this as the general shape of the bug rather than a precise sequence.
Varonis product impact #
Varonis has assessed the impact of these vulnerabilities across its product portfolio and taken the necessary remediation actions.
| Product | Vulnerability Status | | Varonis SaaS | Not affected | | Varonis DAC | Not affected | | Varonis Atlas | Not affected | | Varonis Interceptor | Previously affected; fully patched |
As of the date of publication, Varonis has identified no signs of compromise associated with these vulnerabilities. All affected Varonis Interceptor environments have been remediated. No customer action is required. The affected Varonis components have been patched, and Varonis SaaS, DAC, and Atlas are not vulnerable to these CVEs.
References
How Varonis can help #
Varonis helps customers address PHP2Shell and other threats by detecting suspicious lateral movement and abnormal data access, then automatically contains compromised accounts to protect sensitive data.
Managed Data Detection and Response (MDDR) provides an added layer of protection alongside patching, with Varonis experts monitoring data activity 24x7x365, investigating threats such as stolen credentials accessing sensitive data, and taking action to contain them. Customers gain around-the-clock expert coverage without having to staff their own 24x7 team.
Summary #
PHP2Shell is a chain born from one unglamorous event: a request that runs out of memory and skips its cleanup. From that single stale pointer, researchers got memory disclosure, two flavors of use-after-free, and a separate OPcache type confusion, all below the application layer and present since PHP 5.4.
What should I do now?
Below are three ways you can continue your journey to reduce data risk at your company:
Schedule a demo with us to see Varonis in action. We'll personalize the session to your org's data security needs and answer any questions.
See a sample of our Data Risk Assessment and learn the risks that could be lingering in your environment. Varonis' DRA is completely free and offers a clear path to automated remediation.
Follow us on LinkedIn, YouTube, and X (Twitter) for bite-sized insights on all things data security, including DSPM, threat detection, AI security, and more.