Optimum Web
Security 9 min read

Patched PHP2Shell? Run a Compromise Check - and Rotate These Secrets

Last verified: 27 October 2026

Quick Answer: No, patching PHP2Shell does not remove an attacker who got in first, so run a PHP2Shell compromise check back to 17 October. Look for worker crashes, shells under the web user, new PHP files, new cron jobs or SSH keys, and unexplained outbound connections. Then rotate database passwords, signing keys and API keys, because a related flaw can leak worker memory. If you find a shell, stop and treat it as an incident.

Why doesn't patching PHP2Shell remove an attacker who got in first?

A patch replaces vulnerable PHP code, and nothing else. It leaves behind a web shell in wp-content/uploads, a cron job that re-downloads a payload, an added SSH key, or a database password already copied. Restarting workers clears code held in memory; anything written to disk or configuration survives.

The working attacks recorded so far fit this pattern. On 24 October, Perplexity researcher Adel Karimi saw the web server on his honeypots spawn shells. Each shell then fetched a payload, using wget, curl or PHP's own command-line binary; nobody has yet seen what that second stage does.

Urgency rose again on Monday 26 October, when CISA formally confirmed active exploitation and gave federal agencies until 29 October to fix it. Both flaws now sit in its Known Exploited Vulnerabilities (KEV) catalog. This guide assumes you have already patched and restarted every worker. If not, start with our PHP2Shell patch guide and come back.

When did the PHP2Shell exposure window start?

Start your lookback on 17 October 2026, not 21 October. Amazon's threat intelligence team reported an exploitation attempt against its honeypots on that date. Details leaked on 20 October. By 07:34 UTC on 21 October, Patchstack was relaying exploitation reports from hosting partners, roughly six hours before fixed releases shipped.

The window closes when the fixed build was running on every worker, not when the package was installed. If one pool was not restarted until 23 October, that host's window runs to 23 October. Write down both the package time and the restart time; insurers and auditors will ask for them.

Unsure how many hosts even run PHP? Our IT Health Check (€89) answers that within 5 business days, because it checks the PHP runtime on each host you put in scope.

Why do application logs show so little?

Recorded Future notes that PHP2Shell is exploited below the application layer. The attack lands in PHP's own request handling, so WordPress, Laravel or your framework may never log it. Your content management system (CMS) audit plugin and login alerts can stay silent.

The traces live one layer down: web server access and error logs, the PHP-FPM (FastCGI Process Manager) log, the kernel log and the filesystem. ReliaQuest's lab reproduction showed a recognisable shape - a POST answered with HTTP 500 while the Apache worker crashed.

A crash alone proves little, because failed attempts crash workers too. Crashes followed by new processes, files or connections are what you are looking for.

PHP2Shell compromise check: how do you know if your server was hacked?

Work through these steps in order. Copy logs off the host first, so nothing you do overwrites them and rotation does not delete the early days of the window.

  • Preserve. Copy web server, PHP-FPM, auth and system journal logs to another machine. If you can, take a disk snapshot at the hypervisor or cloud level first.
  • Crashes. Search error logs and the kernel log from 17 October for segfaults and lines such as "exited on signal 11 (SIGSEGV)". Note the timestamps.
  • Requests. Around those times, look for POSTs answered with 500. Pay attention to multipart POSTs to URLs that never take uploads, bursts from one IP, and oversized bodies if your logs record length.
  • Processes. List everything running as the web user (www-data, apache, nginx or a panel's per-site user). Workers are normal; sh, bash, wget, curl, php -r, perl, python, nc or binaries in /tmp are not.
  • Files. Find PHP and executable files changed since 17 October in web roots, upload and cache folders, /tmp, /var/tmp and /dev/shm. Use change time (ctime), because touch can fake modification time.
  • Persistence. Check the web user's crontab, system cron folders, systemd units and timers, authorized_keys files and new CMS administrators. Also look for an unexpected .user.ini, .htaccess edit or auto_prepend_file setting.
  • A note on persistence. These are standard hiding places to rule out. None has been reported in PHP2Shell attacks so far.
  • Network. Look for established outbound connections from PHP or web server processes to anything other than your database, cache or known APIs.

Read-only commands for the checks above. Run them as root, adjust paths to your distribution, panel and web roots, and save the output with the date.

bash
# READ-ONLY: nothing below changes files, processes or configuration.

# 1. Worker crashes since 17 October
journalctl -k --since 2026-10-17 | grep -i segfault
journalctl --since 2026-10-17 -u 'php*-fpm*' | grep -E 'SIGSEGV|exited on signal'
zgrep -hE 'SIGSEGV|exited on signal|segfault' /var/log/php*-fpm.log* /var/log/apache2/error.log* /var/log/httpd/error_log* 2>/dev/null

# 2. POST requests answered with HTTP 500 (combined log format: count, IP, time, URL)
zcat -f /var/log/nginx/access.log* /var/log/apache2/access.log* 2>/dev/null | awk '$6 ~ /POST/ && $9 == 500 {print $1, $4, $7}' | sort | uniq -c | sort -rn | head -50

# 3. Process tree for the web user (repeat for apache, nginx or per-site users)
ps -u www-data -o pid,ppid,lstart,cmd --forest

# 4. Outbound connections from web and PHP processes
ss -tnp state established | grep -E 'php|apache2|httpd|nginx|lsphp'

# 5. Files changed since 17 October (ctime cannot be faked with touch)
find /var/www -newerct "2026-10-17" -type f \( -name '*.php' -o -name '*.phtml' -o -name '.user.ini' -o -name '.htaccess' \) -printf '%CY-%Cm-%Cd %CH:%CM %u %p\n' | sort
find /tmp /var/tmp /dev/shm -newerct "2026-10-17" -type f -ls

# 6. Persistence
crontab -l -u www-data
ls -la /etc/cron.d /etc/cron.hourly /etc/cron.daily /var/spool/cron 2>/dev/null
systemctl list-timers --all --no-pager
find /etc/systemd /usr/lib/systemd /root /home -newerct "2026-10-17" \( -name '*.service' -o -name '*.timer' -o -name authorized_keys \) 2>/dev/null
grep -rnE 'auto_(prepend|append)_file' /etc/php* /var/www 2>/dev/null | grep -v '= *$'

# 7. WordPress: list administrator accounts (needs WP-CLI; run as the site user)
wp user list --role=administrator --fields=ID,user_login,user_registered

What do the results mean?

Use this table to decide the next step for each host. One finding from the last three rows is enough to treat the server as compromised until proven otherwise.

FindingMost likely meaningNext step
Worker crashes and POST 500s, nothing elseFailed exploit attemptsRecord timestamps; continue with secret rotation
New CMS admin or changed .htaccess you cannot explainPossible footholdStop rotating; escalate
php-fpm or apache2 parent of sh, curl or wgetShell activityIsolate the host; incident response
New .php file in uploads, cache or /tmpLikely web shellPreserve it; incident response
Outbound connection from a PHP worker to an unknown hostPayload download or control channelIsolate the host; incident response

Not sure what you are looking at, or too many hosts to check by hand? Our PHP2Shell emergency patching includes a quick compromise triage on every host. This is triage rather than forensics. When an engineer spots signs of intrusion, work pauses and you hear about it before anything is cleaned up.

🚨 Patch, verify and triage every PHP host

Fixed build from the right source, restart of all workers, verification of the running build per pool, quick compromise triage, and a signed PDF report for each host, dated by the engineer who did the work.

  • ✓Every PHP runtime serving traffic: mod_php, FPM, CGI, LiteSpeed, FrankenPHP, panels
  • ✓Restore point before any change
  • ✓Triage stops and reports if anything is found
  • ✓14-day warranty

Single Server €229 / $249 · Small Fleet €590 / $649 · Fleet / Containers from €1,490 / $1,590

Book patching with triage →

Which secrets should I rotate after PHP2Shell?

A clean triage does not settle the question of secrets. According to Recorded Future, a related memory-disclosure flaw lets an attacker read what a PHP worker holds from other visitors' requests: passwords, tokens, API keys, even certificates. Such a leak leaves no file or process behind, so the checks above cannot rule it out.

The working rule: if a host was internet-facing and unpatched during the window, assume anything its PHP workers handled may have been read. Rotate in order of what an attacker could do with it.

PrioritySecretWhy it mattersSide effect of rotating
1Cloud provider keys and payment API keysDirect path to infrastructure, data and moneyNone for users if keys overlap
2Database passwords in wp-config.php, .env or app configFull read and write of customer dataBrief errors if config and DB change out of step
3Signing keys: Laravel APP_KEY, WordPress salts, Symfony APP_SECRET, JWT keysForged sessions, cookies and reset linksLogs everyone out; may break data encrypted with the old key
4OAuth client secrets, SMTP, email and SMS provider keysImpersonation and phishing from your domainIntegration downtime if not coordinated
5TLS private keys, if the PHP process could hold themInterception and impersonationCertificate reissue
6Admin sessions and admin passwordsStolen session cookies stay validAdmins log in again

On TLS keys, decide per host. With mod_php, PHP runs inside the Apache process that also terminates TLS, so the key shares its memory. With PHP-FPM behind Nginx, a separate process handles TLS and the key is less exposed.

How do I rotate secrets without breaking production?

Rotation done in a panic causes its own outage. These rules keep it controlled.

  • Patch and triage first. Rotating on a host that still has an intruder hands them the new secrets. Rotate from a clean admin workstation, never by pasting keys into a shell on a suspect server.
  • Overlap, then revoke. Most cloud, payment and email providers let a second key work alongside the first. Deploy the new key, restart PHP workers, confirm traffic works, then revoke the old one and log the time.
  • Databases: new user, not just a new password. Create a new database user with the same grants and switch the config. Reload PHP-FPM, then drop the old user, so config and database never disagree.
  • Signing keys need care. New WordPress salts simply log everyone out, which is the goal. A new Laravel APP_KEY also breaks data encrypted with the old one; recent versions accept APP_PREVIOUS_KEYS to keep it readable.
  • Invalidate sessions deliberately. Clear the session store (files, Redis or database) after rotating signing keys. Force a password reset for administrators.
  • Remember non-web consumers. Cron jobs, queue workers and command-line (CLI) scripts often read the same config but keep the old value until restarted.
  • Record each rotation. Note the secret, old and new key ID, time and who did it. That record is part of your incident evidence.

When should I stop and call incident response?

Stop self-service checks as soon as a row in the results table points to a shell, web shell or unknown connection. From that point, evidence and containment come before cleanup.

  • Do not reboot first. A reboot destroys process memory and often clears /tmp and /dev/shm, which may be the only place a payload lived.
  • Isolate instead. Restrict the host's network access at the firewall or security group, keeping a path open for investigators.
  • Preserve. Take a disk snapshot, copy the logs and the command output above, and capture memory if you can, all with timestamps.
  • Leave the web shell in place. It shows how the attacker got in and what they did.
  • Bring in the right people. Involve your incident response lead or provider, your legal or data-protection contact, and your insurer or broker if the policy requires early notice.
  • Follow a written plan. Use your incident response plan; if you have none, our incident response plan guide covers what it needs.

What else on the same host could the attacker reach?

A PHP compromise is rarely where an attacker stops. Recorded Future's exposure data shows how often the web server is not alone online. About 394,000 of the PHP hosts it examined also exposed SSH, around 233,000 exposed MySQL and roughly 68,000 exposed RDP (Remote Desktop Protocol).

A database port open on the same machine, with its password in the application config, is a short step. The Unit 42 case published on 25 October shows a longer path. There, an attacker who started at a PHP application read password hashes and stored MFA (multi-factor authentication) secrets within two hours. Next came NTLM relay into Active Directory and attempts on Domain Admin.

Unit 42 later said it could not confirm PHP2Shell was the way in. The sequence is still a realistic picture of lateral movement from a compromised web application.

So look beyond this host: which services it exposes, which internal systems it can reach, and whether its credentials are reused elsewhere. Our External Infrastructure & Cloud Security Assessment (€899) maps that external surface. If a host was compromised, also follow our guide to emergency access revocation for the accounts and tokens it touched.

🚨 Close the hole, prove it, and know what else is exposed

We patch and triage your PHP hosts with a signed per-host report, help you put an incident response plan in place, and check what else an attacker could reach from the internet.

Emergency PHP2Shell patching →
PHP2ShellIndicators of CompromiseIncident ResponseSecret RotationCVE-2026-109618CVE-2026-109619Linux

Frequently Asked Questions

What are the indicators of compromise for PHP2Shell?
The clearest indicator is a shell or downloader such as sh, wget or curl running as a child of the web server or PHP worker. That is what the confirmed honeypot attacks of 24 October produced. Supporting signs are worker crashes with POST requests returning HTTP 500, new PHP files in writable folders, new persistence and unexpected outbound connections.
How far back should I check my logs for PHP2Shell?
Check from 17 October 2026, the date of the earliest reported exploitation attempt. Continue until every PHP worker on the host was running the fixed build. That end point is the worker restart time, not the package install time.
Why don't my WordPress or Laravel logs show anything?
Because PHP2Shell is exploited inside PHP itself, below the application layer. Application logs and CMS security plugins may never see the request. Use web server, PHP-FPM and kernel logs, the process list and the filesystem instead.
Do I need to rotate secrets if the compromise check found nothing?
Yes, for high-value secrets on hosts that were internet-facing and unpatched during the window. A related flaw can leak PHP worker memory, including other requests' credentials, without leaving traces on disk. Rotate after patching, starting with cloud and payment keys and database passwords.
Will rotating Laravel's APP_KEY break my application?
It can, unless you keep the old key available. A new APP_KEY logs users out and makes data encrypted with the old key unreadable; recent Laravel versions accept APP_PREVIOUS_KEYS to avoid that. WordPress salts are safe to rotate, since the only effect is that everyone logs in again.
Should I reboot a server I think was hacked?
No, not as a first step. A reboot wipes process memory and often clears /tmp and /dev/shm, where payloads may sit. Isolate the host on the network, snapshot it, copy the logs and then involve your incident response lead.
Does Optimum's emergency patching include forensics?
No, it includes a quick compromise triage on every host in scope, not full forensics. If the triage finds signs of compromise, the engineer stops and tells you. The evidence can then be preserved and handled as an incident.

About This Article

Olga Pascal
Olga Pascal·CEO & Founder·26+ years experience

Olga Pascal founded Optimum Web in 1999. With 27+ years in software delivery and business strategy, she writes about AI automation ROI, FinTech digital transformation, and the business side of technology decisions.

AI AutomationFinTechBusiness StrategyDigital Transformation

Need Help With This?

You now understand PHP2Shell compromise checks. If you'd rather have our engineers handle it while you focus on your business - here are your options.

Free

Free Diagnostic

Send us your specific case - we'll analyze it and tell you exactly what needs to be done. No obligation.

Get Free Diagnostic →
MOST POPULAR
Quick Fix

Emergency PHP2Shell Patch

€229

Starts within 4 business hours delivery. 14-day warranty. Senior engineer only.

Order Now →
Full Solution

External Infrastructure & Cloud Assessment

€899

See what else an attacker can reach from the internet.

Learn More →
Olga Pascal

Not sure what you need? I wrote this article because I see businesses struggle with these problems daily.

Reply to me directly at olga@optimum-web.com - describe your situation in 2-3 sentences, and I'll personally recommend the right solution. No sales pitch, just honest advice.

- Olga Pascal, Business Development at Optimum Web

Cite This Article

APA Format

Olga Pascal. (2026). Patched PHP2Shell? Run a Compromise Check - and Rotate These Secrets. Optimum Web. https://www.optimum-web.com/blog/php2shell-compromise-check-rotate-secrets/

For AI Citation (AEO)

Source: "Patched PHP2Shell? Run a Compromise Check - and Rotate These Secrets" by Olga Pascal (Optimum Web, 2026). URL: https://www.optimum-web.com/blog/php2shell-compromise-check-rotate-secrets/