phphackfix
Incident checklist

Your site is hacked. Do these seven things, in this order.

Most damage in a website compromise happens after the discovery — either the attacker keeps access because nobody changed the passwords, or the owner deletes the visible symptom (the spam page, the redirect) and the actual door stays open.

First, one question that changes everything: was the entry point this week's PHP flaw (CVE-2026-109618 / CVE-2026-109619)? If the server was unpatched and reachable after 17 October 2026, treat that as the likely door. What that means →

1. Preserve, then contain — in that order

Copy the evidence before you clean. Once you delete a file, you have lost the only description of what the attacker did.

sudo mkdir -p /root/ir-$(date +%F)
sudo cp -a /var/log /root/ir-$(date +%F)/logs 2>/dev/null
sudo tar czf /root/ir-$(date +%F)/www.tgz /var/www /home/*/public_html 2>/dev/null
sudo ps -eo pid,ppid,user,lstart,args --forest > /root/ir-$(date +%F)/ps.txt
sudo ss -tunap > /root/ir-$(date +%F)/net.txt

Then block the symptom, not the evidence: put the site in maintenance mode or pull it from the load balancer. If you have shell access and active intrusion, take the host off the network rather than shutting it down — you keep the memory, the process table and the connections.

On shared hosting you cannot do any of this. Open a security ticket and ask the host to preserve access logs; ask explicitly for the PHP version history and the date the runtime was last restarted.

2. Work out how they got in

Check these three in parallel — the answer is usually in one of them:

# PHP errors that suggest the request never reached your code
grep -h 'Allowed memory size' /var/log/php*.log /var/log/apache2/error.log 2>/dev/null \
  | grep 'in Unknown on line 0' | tail -30

3. Find the shell

Attackers leave a small file that lets them run commands, then hide it. Search by location first — a PHP file in an uploads folder is never legitimate — then by shape.

# 1. PHP where PHP should never be
find /var/www /home -type f -name '*.php' \
  \( -ipath '*uploads*' -o -ipath '*cache*' -o -ipath '*images*' -o -ipath '*tmp*' \) 2>/dev/null

# 2. Files changed in the incident window
find /var/www -name '*.php' -newermt '2026-10-16' -printf '%TY-%Tm-%Td %TH:%TM %10s %p\n' | sort

# 3. Configuration hijacks (persistence with no shell file at all)
grep -REn 'auto_prepend_file|auto_append_file' /etc/php /etc/apache2 /var/www 2>/dev/null
find / -name '.user.ini' -newermt '2026-10-01' 2>/dev/null

If you run WordPress, its own checksum tool is the fastest integrity check available:

wp core verify-checksums
wp plugin verify-checksums --all
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
ls -la wp-content/mu-plugins/

A file that matches nothing above is not proof of a clean site. An attacker who only used the memory-disclosure bug steals credentials and never writes a file at all.

Ad slot — replace with your AdSense unit

4. Rotate every secret the site could read

This is the step people skip, and it is the one that decides whether the attacker comes back. If they had code execution as the web user, they could read anything your application could read.

Rotating the salts logs every user out, including any session the attacker still holds. That is the point.

5. Clean or rebuild — the honest test

SituationWhat to do
One shell found, no new users, no cron, no SSH keys, immutable infrastructure availableRebuild from image, restore data only, scan uploads
New local user, SSH key, cron job, systemd unit or ld.so.preload entryRebuild. Do not try to clean.
No shell found, but logs show code executionRebuild. You cannot enumerate the damage.
Only exposure, no execution evidencePatch, rotate secrets, monitor for 7 days
Shared hostingAsk to be moved to a fresh container; assume neighbours were exposed too

Cleaning in place is defensible only when you can list every file the attacker could write, verify all of it against a known-good copy, and prove there is no persistence outside the web root. If any of those is “probably”, rebuild.

6. Watch for the return visit

Re-infection within a few days means persistence you missed, not bad luck. Minimum monitoring for a week: new files in the web root, new admin users, outbound connections from the web tier, and unexplained CPU spikes (miners are the most common payload).

7. Report, if it applies to you

In the US, the FBI asks for incidents via ic3.gov or a local field office. In the EU and UK, check your 72-hour breach-notification obligation if personal data may have been accessed — and with a memory-disclosure flaw, “may have been” is the honest standard. Tell your insurer inside the notification window in your policy, and tell your clients before they read about it.

Do not do this: do not paste your logs, database dumps or wp-config.php into a random online scanner, and do not install “nulled” cleanup plugins. Both are common second compromises. If you hire help, ask for a named person, a scope and a written report.

Want the whole sequence run for you?

Containment, entry-point analysis, shell hunt, credential rotation and a written record of what was found — for one site or a small estate.

Get help now Patch instead — read the runbook