PHP's release team has rebuilt and re-released the official Windows packages for PHP 8.2, 8.3, 8.4, and 8.5 — the second Windows security update in five days — to remediate CVE-2026-111497, a memory corruption vulnerability in the Brotli compression library bundled with those packages. The flaw is reachable through PHP's cURL extension when it automatically decompresses HTTP responses. While cURL's automatic decompression is disabled by default, any application that enables it (a common pattern for API clients, crawlers, feed parsers, and integrations that set CURLOPT_ENCODING) becomes a memory-corruption target: a malicious HTTP response served by an attacker-controlled or compromised upstream can corrupt memory in the PHP process and potentially achieve code execution.
This is a serious exposure for a specific but large population: organizations running PHP on Windows (IIS + FastCGI, Apache on Windows, standalone php-cgi/php.exe workers, CI runners, and Windows-hosted Laravel/Symfony/WordPress applications). The vulnerable code lives in a bundled third-party library, which means a standard apt/yum package update cadence does not apply — Windows PHP deployments must be updated with the rebuilt packages directly from php.net. If your servers fetch remote content with cURL decompression enabled, treat this as an urgent patch cycle, not a routine one.
Technical Analysis
Affected Products and Platforms
- PHP official Windows builds for versions 8.2, 8.3, 8.4, and 8.5 (thread-safe and non-thread-safe packages distributed via windows.php.net)
- The vulnerable component is the Brotli compression library shipped inside those packages (linked into the cURL extension path)
- Linux builds are not the subject of this advisory — Linux distributions link against system Brotli/cURL and are patched through their own package managers
- The affected runtime processes are typically
php-cgi.exe(IIS/FastCGI),php.exe(CLI/scheduled tasks/queue workers), andhttpd.exewhen Apache on Windows loads PHP
CVE and Severity
- CVE-2026-111497 — memory corruption in the Brotli decompression path, with potential for remote code execution
- The advisory describes the impact as memory corruption that an attacker could leverage to run arbitrary code in the context of the PHP process — on a web server, that is the application pool / web service identity, which frequently has database credentials, filesystem access to application secrets, and lateral-movement potential
How the Vulnerability Works (Defender's View)
The attack chain is straightforward and dangerous because it is server-side and request-driven:
- A PHP application on Windows makes an outbound HTTP request via the cURL extension with automatic decompression enabled (e.g.,
curl_setopt($ch, CURLOPT_ENCODING, '');or explicitly requesting Brotli viaAccept-Encoding: br). - The upstream server — attacker-controlled, or a legitimate third-party API/CDN endpoint that has been compromised or is serving attacker-influenced content — returns a crafted Brotli-compressed response body.
- The bundled Brotli decoder processes the malicious stream, triggering memory corruption inside the PHP process.
- With sufficient exploit engineering, the corruption is steered into arbitrary code execution under the web service account.
Key exploitation requirements defenders should note:
- Automatic decompression must be enabled. cURL leaves it off by default, which sharply reduces the exposed population — but
CURLOPT_ENCODINGis routinely enabled in codebases to save bandwidth on API calls. Grep your codebases; you will likely find it. - The PHP application must make outbound HTTP requests to an untrusted or compromisable endpoint. SSRF-style paths, webhook fetchers, URL preview features, importers, and headless crawlers are prime candidates.
- Exploitation is inbound-data-driven: no authentication to your application is required if the attacker can influence or serve the upstream response.
Exploitation Status
At the time of publication, the advisory does not confirm in-the-wild exploitation, and the CVE has not been listed in the CISA Known Exploited Vulnerabilities catalog. However, the pattern here — a client-side decompression bug reachable from server-side HTTP fetches — is exactly the class of bug that gets weaponized quickly once technical details circulate, particularly against applications that fetch user-supplied URLs. Assume PoC development is underway and patch accordingly.
Detection & Response
Detection strategy here has three layers: (1) identify vulnerable PHP installations, (2) hunt for post-exploitation behavior from PHP processes (the most reliable signal, since memory-corruption exploits manifest as the PHP process doing things PHP never does), and (3) inventory applications that enable cURL decompression.
Sigma Rules
The highest-fidelity behavioral detection for this class of flaw is the PHP runtime spawning child processes or making unusual network connections. A weaponized Brotli RCE will almost invariably hand off to a shell, an interpreter, or a dropped binary.
---
title: PHP Process Spawning Command Shell or Script Interpreter
description: Detects php.exe or php-cgi.exe spawning cmd.exe, powershell.exe, or other interpreters — consistent with post-exploitation of a PHP process via CVE-2026-111497 (Brotli memory corruption) or similar PHP RCE.
logsource:
category: process_creation
product: windows
detection:
selection_parent:
ParentImage|endswith:
- '\php.exe'
- '\php-cgi.exe'
- '\php-win.exe'
selection_child:
Image|endswith:
- '\cmd.exe'
- '\powershell.exe'
- '\pwsh.exe'
- '\wscript.exe'
- '\cscript.exe'
- '\mshta.exe'
- '\rundll32.exe'
- '\certutil.exe'
- '\bitsadmin.exe'
- '\curl.exe'
condition: selection_parent and selection_child
falsepositives:
- Legitimate PHP applications invoking system tools (Composer, deployment scripts, Artisan/PowerShell integrations)
- Scheduled maintenance scripts
level: high
---
title: PHP CGI Process Writing Executable Content to Suspicious Locations
description: Detects php-cgi.exe or php.exe dropping executable files into temp, ProgramData, or web-accessible directories — a common post-exploitation staging behavior following PHP process compromise.
logsource:
category: file_event
product: windows
detection:
selection:
Image|endswith:
- '\php.exe'
- '\php-cgi.exe'
TargetFilename|endswith:
- '.exe'
- '.dll'
- '.ps1'
- '.bat'
- '.hta'
- '.aspx'
- '.php'
selection_paths:
TargetFilename|contains:
- '\Temp\'
- '\ProgramData\'
- '\inetpub\wwwroot\'
- '\AppData\Local\Temp\'
condition: selection and selection_paths
falsepositives:
- CMS/plugin installers and Composer operations writing PHP files
- Application build and deployment pipelines
level: medium
---
title: PHP Process Outbound Connection Followed by Inbound Shell Behavior
description: Detects php.exe or php-cgi.exe establishing outbound network connections to rare external destinations. Benign cURL use is expected, but baselining this reveals compromised applications reaching attacker infrastructure after CVE-2026-111497 exploitation.
logsource:
category: network_connection
product: windows
detection:
selection:
Image|endswith:
- '\php.exe'
- '\php-cgi.exe'
filter_common:
DestinationIp|startswith:
- '10.'
- '172.16.'
- '192.168.'
- '127.'
condition: selection and not filter_common
falsepositives:
- Legitimate outbound API calls from PHP applications (payment gateways, SaaS integrations)
- Update checks and package managers
level: low
KQL (Microsoft Sentinel / Defender)
Use this to hunt across your fleet for the post-exploitation pattern — PHP spawning shells — and to baseline which PHP processes make outbound network connections at all:
// Hunt 1: PHP runtime spawning command shells or LOLBins (post-exploitation indicator)
DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName in~ ("php.exe", "php-cgi.exe", "php-win.exe")
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "wscript.exe", "cscript.exe",
"mshta.exe", "rundll32.exe", "certutil.exe", "bitsadmin.exe", "curl.exe")
| project TimeGenerated, DeviceName, InitiatingProcessCommandLine, FileName, ProcessCommandLine,
AccountName, InitiatingProcessId, ProcessId
| order by TimeGenerated desc;
// Hunt 2: Inventory of PHP processes making outbound network connections (baseline + anomaly)
DeviceNetworkEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName in~ ("php.exe", "php-cgi.exe")
| where RemoteIPType == "Public"
| summarize ConnectionCount = count(), DistinctDestinations = dcount(RemoteUrl),
Destinations = make_set(RemoteUrl, 20)
by DeviceName, InitiatingProcessCommandLine
| order by DistinctDestinations desc;
// Hunt 3: Identify PHP installations and versions via process command lines / file paths
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where ProcessVersionInfoOriginalFileName has "php"
or FolderPath has_any ("\\php\\", "\\php8")
| summarize LastSeen = max(TimeGenerated) by DeviceName, FolderPath, FileName, ProcessVersionInfoProductVersion
| order by DeviceName asc;
Velociraptor VQL
Deploy this hunt across Windows servers to inventory running PHP processes and spot suspicious child processes and network connections from PHP — useful for scoping both vulnerable installs and active compromise:
-- Inventory PHP processes, their child processes, and their network connections
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Exe =~ '(?i)php(-cgi|-win)?\.exe$'
OR Name =~ '(?i)^php'
-- Enumerate network connections held by PHP processes
LET php_pids = SELECT Pid FROM pslist() WHERE Name =~ '(?i)php'
SELECT Pid, Name, LocalAddr, LocalPort, RemoteAddr, RemotePort, Status
FROM netstat()
WHERE Pid in (SELECT Pid FROM php_pids)
AND RemoteAddr !~ '^(127\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|0\.0\.0\.0)'
Remediation / Verification Script (PowerShell)
Run this on Windows servers to enumerate installed PHP versions, flag builds that need the updated packages, and audit application code for cURL decompression usage:
# =============================================================
# CVE-2026-111497 — PHP Windows Brotli Vulnerability Assessment
# =============================================================
# 1. Locate PHP installations and report versions
$phpPaths = @()
$searchRoots = @("C:\php", "C:\Program Files\PHP", "C:\tools\php", "C:\inetpub")
foreach ($root in $searchRoots) {
if (Test-Path $root) {
$phpPaths += Get-ChildItem -Path $root -Recurse -Filter "php.exe" -ErrorAction SilentlyContinue
}
}
# Also check running services (IIS FastCGI handlers often reference php-cgi.exe)
$phpPaths += Get-CimInstance Win32_Process -Filter "Name='php-cgi.exe' OR Name='php.exe'" |
Select-Object -ExpandProperty ExecutablePath -Unique |
ForEach-Object { Get-Item $_ }
foreach ($php in ($phpPaths | Sort-Object FullName -Unique)) {
$ver = & $php.FullName -v 2>$null | Select-Object -First 1
$verInfo = $php.VersionInfo
Write-Host "[FOUND] $($php.FullName)"
Write-Host " Version: $ver"
Write-Host " FileVersion: $($verInfo.FileVersion) Modified: $($php.LastWriteTime)"
# Flag 8.2-8.5 builds as requiring verification against the rebuilt packages
if ($ver -match "PHP 8\.[2-5]") {
Write-Warning " -> PHP 8.2-8.5 on Windows: VERIFY this build is the re-released patched package from windows.php.net (CVE-2026-111497)"
}
}
# 2. Check whether the cURL extension is loaded and whether Brotli support is present
foreach ($php in ($phpPaths | Select-Object -First 3)) {
Write-Host "`n[MODULES] $($php.FullName)"
& $php.FullName -m 2>$null | Select-String -Pattern "curl"
$curlInfo = & $php.FullName -r "print_r(curl_version());" 2>$null
if ($curlInfo -match "brotli") {
Write-Warning " cURL reports Brotli support -> decompression path is present; audit CURLOPT_ENCODING usage"
}
}
# 3. Audit application code for cURL automatic decompression enablement
$codeRoots = @("C:\inetpub\wwwroot", "C:\sites", "D:\apps")
foreach ($codeRoot in $codeRoots) {
if (Test-Path $codeRoot) {
Write-Host "`n[CODE AUDIT] Scanning $codeRoot for CURLOPT_ENCODING usage..."
Get-ChildItem -Path $codeRoot -Recurse -Include *.php -ErrorAction SilentlyContinue |
Select-String -Pattern "CURLOPT_ENCODING|Accept-Encoding.*br|curl_setopt.*ENCODING" |
ForEach-Object { Write-Warning " $($_.Path):$($_.LineNumber): $($_.Line.Trim())" }
}
}
# 4. Check IIS FastCGI handler mappings to find PHP runtimes in use by web sites
try {
Import-Module WebAdministration -ErrorAction Stop
Get-WebConfiguration -Filter "system.webServer/fastCgi/application" |
ForEach-Object { Write-Host "`n[IIS FASTCGI] $($_.fullPath) $($_.arguments)" }
} catch {
Write-Host "`n[IIS] WebAdministration module not available or IIS not installed."
}
Write-Host "`n[DONE] Review flagged installs and update to the re-released Windows packages from https://windows.php.net/download/"
Remediation
- Patch immediately — replace the PHP packages, don't wait. Download the re-released Windows builds for PHP 8.2/8.3/8.4/8.5 from the official source: https://windows.php.net/download/. Verify the build date and hash match the current published packages — the original vulnerable builds were replaced, so simply "being on 8.3.x" is not sufficient; you need the rebuilt binaries. Update every Windows host running PHP, including staging, CI runners, and developer workstations that fetch remote content.
- Inventory and constrain cURL decompression. Search all PHP codebases for
CURLOPT_ENCODING(including the common empty-string formcurl_setopt($ch, CURLOPT_ENCODING, ''), which enables all supported encodings including Brotli). If automatic decompression is not functionally required, remove it. If it is required, restrict it to gzip/deflate only (e.g.,CURLOPT_ENCODING, 'gzip') as a compensating control until patching is confirmed. - Reduce outbound-fetch trust. Applications that fetch user-supplied or third-party URLs (SSRF-adjacent features) are the highest-risk targets. Enforce egress allowlists so PHP processes can only reach approved upstream hosts, and route outbound cURL through a controlled proxy where feasible.
- Harden the blast radius. Run PHP application pools under least-privilege identities with no interactive logon, restrict write access outside application directories, and ensure
disable_functionsblocksexec,shell_exec,system,passthru, andproc_openwhere the application doesn't need them — this breaks the most common post-exploitation handoff from a compromised PHP process. - Deploy the detections above before and during patching. If
php-cgi.exespawnscmd.exeorpowershell.exein production, investigate immediately — treat it as a potential compromise, not a tuning exercise. - Verify post-patch. Re-run the assessment script after updates; confirm cURL's reported Brotli library reflects the fixed build and that the package file timestamps match the re-release.
Reference: PHP advisory coverage at The Hacker News (https://thehackernews.com/2026/10/php-issues-second-windows-security.html) and the official downloads at https://windows.php.net/download/.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.