Was PHP2Shell used against you? Detection and response
Patching closes the hole. It does not tell you whether someone used it first. This guide covers every server that ran a vulnerable PHP version on the internet before it was patched. Bear in mind that the most telling signals of this attack occur below the application, where most logging never looks.
What the threat picture looked like on disclosure day
The earliest known attempt came before the vulnerabilities were public. Amazon recorded one on its MadPot honeypots on 17 October, four days before disclosure. On 21 October, before the release, it saw several separate actors, and that day it described PHP2Shell as broadly exploited in the wild. It also said it was unclear whether the attempts would succeed against real systems. OffSeq's own decoy fleet saw nine sources in the first 48 hours, the first about sixteen hours before the fix; the field-data guide has the detail. Amazon's advice is to start any investigation from at least 17 October, not from the disclosure date.
Other vendors' claims from 21 October differ, so read them carefully. On 21 October, Cloudflare said it was seeing early attacks and attackers mutating payloads to get past its rules; watchTowr reported exploitation attempts against its honeypot network; Fastly said there was evidence of attacks before disclosure; Patchstack relayed reports from hosting partners, then said its own telemetry showed only probing. None published evidence of a successful compromise or indicators of compromise.
On the other side, Cisco Talos had not seen exploitation as of 14:00 UTC on 21 October, the PHP security team found no functional public exploit at release, watchTowr told SecurityWeek that nobody had been successful to date, and neither CVE was in CISA's Known Exploited Vulnerabilities catalogue that day. The direction of travel is not in doubt: a leaked demonstration video accelerated proof-of-concept work, and attempts were already hitting sensors on day one.
Why logs may show nothing
The vulnerable code runs inside PHP's request handling, before your application is involved and often before anything is logged. The PHP advisory for CVE-2026-109619 says stale state can be used without a predictable log entry, and that the absence of an error in logs is not proof of safety. Memory disclosure is quieter still: the researchers describe reading worker memory without executing any code, which tools that watch for malicious commands will not see.
So the question is not "do the logs show an attack" but "was this server exposed while vulnerable, and what would an attacker have been able to reach". The answer to the second question decides how far to go.
Signals in error logs
| Signal | Why it matters | Caveat |
|---|---|---|
Allowed memory size of … exhausted … in Unknown on line 0 | Memory ran out while PHP was parsing the request, before any script ran. CrowdStrike and Fastly both single this out; an out-of-memory error in your own code names a real file and line | A failed exploit can look like this too. CrowdStrike notes a successful one may leave nothing else |
| Bursts of segmentation faults or FPM children exiting on a signal | Fastly describes dozens of Apache segmentation faults in minutes, followed by one slow successful response, as the pattern of an exploit searching for memory addresses | Isolated crashes are normal. Look for clusters |
Warnings, deprecations or fatal errors repeated before scripts run, and Maximum execution time exceeded | The PHP advisory for CVE-2026-109619 lists these as things to review | Noisy on many systems; compare with your baseline |
log_errors=On, a working error_log and error_reporting=E_ALL in startup configuration during an isolated audit.# memory exhaustion before any script ran
grep -h "in Unknown on line 0" /var/log/php*-fpm.log /var/log/apache2/error.log /var/log/httpd/error_log 2>/dev/null
# clusters of worker crashes
grep -hE "Segmentation fault|exited on signal" /var/log/php*-fpm.log /var/log/apache2/error.log 2>/dev/null | tail -50
Signals in requests and responses
- A
PHP_SESSION_UPLOAD_PROGRESSfield in multipart uploads, especially on pages that have no upload progress bar. It is a legitimate PHP feature and the default field name, which is why Corelight and Fastly call it a lead rather than proof. - Very long form-field names, deep
[nesting, or a field with no name, and URL-encoded POST bodies of more than a megabyte or two, which Fastly notes legitimate forms almost never send. - Oversized
Set-Cookie: PHPSESSIDvalues in responses. Wiz and Imperva describe worker memory being sent back to the attacker this way; Imperva puts the leak at roughly 67 KB. - Many large POSTs from one address in a short period. Third-party analysis of a public proof of concept describes hundreds of oversized requests over about a quarter of an hour.
Most web servers do not log request bodies or response cookies, so these are usually found in WAF, CDN or IDS data rather than access logs. Network detection also needs to see decrypted HTTP: Corelight and Check Point both note that encrypted traffic which is not inspected passes their signatures untouched.
Signals of what came next
If an attack succeeded, what follows looks like any web server compromise, and this is where detection is strongest. CrowdStrike calls endpoint behaviour monitoring the primary line of defence, because the exploit itself is invisible at the HTTP layer while its outcome is not.
- PHP-FPM, php-cgi, Apache or LiteSpeed processes starting
sh,bash,curl,wget,python,perlorncthat your application does not normally start. Baseline first: PHP'smail()runs sendmail through/bin/sh. - New or modified
.phpfiles, especially in upload, cache and temporary directories. - New cron jobs, new system or application accounts, new SSH keys.
- Outbound connections from the web server to unfamiliar hosts shortly after inbound POST requests.
# PHP files changed in the last 7 days under the web root
find /var/www -name '*.php' -mtime -7 -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort
# processes whose parent is a PHP or web server worker
ps -eo pid,ppid,user,lstart,cmd --forest | grep -B1 -E '\b(sh|bash|curl|wget|nc|python3?|perl)\b'
If you find something
- Isolate, do not wipe. Disconnect the host from the network or block its traffic, but keep it running if you can: memory holds evidence that a reboot destroys.
- Preserve evidence before you rebuild: a memory capture, a disk image, web server and PHP logs, WAF and CDN logs for the exposure window.
- Assume secrets are gone. Rotate database passwords, API keys, session signing keys and TLS private keys that the server held or could reach. Memory disclosure can expose them without leaving a trace.
- Rebuild from a known-good image with the fixed PHP release, rather than cleaning the compromised system.
- Check what the server could reach. A web server is a foothold; look at the database, internal services and any credentials it held.
- Mind the reporting deadlines. If you are covered by NIS2, a significant incident needs an early warning to the national CSIRT within 24 hours of becoming aware of it. Under the GDPR, a personal data breach goes to the supervisory authority within 72 hours where feasible. In Latvia, report to CERT.LV.
If you find nothing
Document what you checked, for which period and with what result, alongside the inventory and patch dates. If the server held valuable secrets and was exposed for any length of time, rotating them is still cheap insurance, because the quietest version of this attack leaves nothing to find.
Sources
- Amazon Threat Intelligence identifies PHP2Shell exploitation prior to public disclosure in MadPot The earliest known attempt on 17 October, broad exploitation after release, indicators, and the advice to investigate from 17 October.
- GHSA-6wmf-4rv5-p3rp: RCE via stale global state Log review advice and the warning that absence of errors is not proof of safety.
- CrowdStrike Protects Customers from Threats Delivered via PHP2Shell The "in Unknown on line 0" signal and post-exploitation detection.
- Fastly's Proactive Protection for PHP2Shell Request shapes, crash bursts and process signals.
- PHP2Shell: When PHP Runs Out of Memory at the Wrong Moment Memory returned through the session cookie.
- php2shell: Zeek and Suricata Detections for PHP RCE Open-source Zeek and Suricata detections, and their stated limits.
- php2shell: What We Know About the Leaked Critical PHP Vulnerabilities Post-exploitation hunting leads.
- Two critical RCEs in PHP core No exploitation observed as of 21 October, 14:00 UTC.
- PHP2Shell Patches Land as First Exploitation Attempts Hit Sensors Attempts on honeypots, and no successful attempt observed.
- Major security alert: PHP vulnerable to critical RCE, attacks ongoing Reports from hosting partners, then telemetry showing only probing.
- Cloudflare deploys protections against php2shell vulnerability Observed attack traffic and payload mutation.
- Today's PHP Security Release, and How We're Strengthening PHP Security No functional public exploit identified at release.
Questions
Related questions
Our logs are clean. Are we safe?
Should we test our servers with a public exploit?
Are there indicators of compromise to block?
p2shell boundary string; see the field-data guide. Use them to search logs rather than as a block list, and detect behaviour as well as strings: tools change.Keep reading
More guides
-
Patching PHP2Shell: platform by platform
Where the fixed PHP packages are for Debian, Ubuntu, RHEL and its rebuilds, Fedora, SUSE, Alpine, Amazon Linux, Docker, control panels and managed hosts, and how to make sure the new binary is the one running.
Read the guide -
PHP2Shell on PHP 8.1, 8.0, 7.x and older
There is no official fixed release below PHP 8.2. What the PHP project provided for 7.4, 8.0 and 8.1, where distribution fixes come from, and what to do with anything older.
Read the guide -
PHP2Shell mitigations when you cannot patch yet
The configuration changes the PHP project published for systems that cannot be updated today, what each one blocks, what it breaks, and the two settings that make things worse.
Read the guide