---
title: "PHP2Shell - Critical vulnerabilities in PHP (CVE-2026-109618, CVE-2026-109619): detection, analysis, and remediation"
description: "Learn about the two critical vulnerabilities in PHP dubbed PHP2Shell."
author: "Nick Frichette, Emile Spir, Eslam Salem"
date: 2026-10-21
category: "emerging threats and vulnerabilities"
tags: ["emerging vulnerability"]
url: "https://securitylabs.datadoghq.com/articles/php2shell-critical-vulnerabilities-in-php/"
---

## Key points and observations

- PHP [disclosed two critical vulnerabilities](https://www.php.net/archive/2026.php#2026-10-20-1), [CVE-2026-109618](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) and [CVE-2026-109619](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp), each with a CVSS v4.0 score of 9.2. We independently reproduced them and confirmed that application-level authentication can't block an attack: PHP processes the malicious request before any application code runs.
- **Only patching fixes these vulnerabilities.** Mitigations circulating in the community, such as setting `session.upload_progress.enabled=0` in the PHP configuration file, don't protect you.
- The exploit doesn't require brute force or crashes. An attacker can bypass [address space layout randomization (ASLR)](https://en.wikipedia.org/wiki/Address_space_layout_randomization) with a calibrated memory layout and a few preparatory requests.
- Successful exploitation doesn't necessarily crash the worker. To investigate, look for large form submissions, memory-exhaustion errors during request initialization, and unexpected shell processes.

## What happened

On October 21, 2026, PHP released security updates for two critical remote code execution (RCE) vulnerabilities, [CVE-2026-109618](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) and [CVE-2026-109619](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp). Both have a Common Vulnerability Scoring System (CVSS) v4.0 score of 9.2. [PHP 8.2.35, 8.3.36, 8.4.27, and 8.5.12](https://www.php.net/archive/2026.php#2026-10-21-1) contain the fixes. PHP 5 through PHP 8.1 are also vulnerable, but these versions are end of life and won't receive patches.

Before the public disclosure, our team built exploits for the vulnerabilities so we could analyze them and develop detections. Our reproduction triggers the out-of-memory corruption described in CVE-2026-109618 on PHP 8.5.11 with an unauthenticated HTTP POST request. The request never reaches the target application's code. Instead, PHP runs the attacker's command while it cleans up the failed request. Any PHP script exposes the vulnerable path, even one that only prints a response.

The two flaws affect different stages of the request life cycle:

- **CVE-2026-109618:** After a memory allocation fails, PHP leaves invalid data behind for its cleanup routine to process.
- **CVE-2026-109619:** A PHP worker can reuse stale state from a previous request.

Our detailed walkthrough covers CVE-2026-109618. Our explanation of CVE-2026-109619 draws on PHP's published advisory.

## Detection and remediation

We're still analyzing and summarizing our findings. We'll update this post as we learn more.

## How Datadog can help

[Datadog Workload Protection](https://docs.datadoghq.com/security/workload_protection/) detects PHP applications that spawn a shell out of the box, which catches exploitation of both vulnerabilities. To check your environment for suspicious activity, use [this Workload Protection query](https://app.datadoghq.com/security/workload-protection/agent-events?query=-%40agent.rule_id%3A%28activity_dump%20OR%20anomaly_detection%20OR%20sysctl_snapshot%20OR%20heartbeat%20OR%20ruleset_loaded%20OR%20self_test%20OR%20ebpfless_hello_msg%20OR%20lost_events%20OR%20abnormal_path%20OR%20no_process_context%20OR%20broken_process_lineage%29%20rule_id%3A%28potential_web_shell_v2%20OR%20potential_web_shell_parent_v2%29&agg_m=count&agg_m_source=base&agg_t=count&category=excludingInternalEvents&clustering_pattern_field_path=%40process.args&fromUser=false&refresh_mode=sliding&stream_sort=timestamp-desc&viz=stream&from_ts=1789994910408&to_ts=1792586910408&live=true).
