techweb24.dev
README.md

How to Check if Your PHP or WordPress Site Was Hacked (and Clean It Up)

Strange redirects, spam pages in Google, a warning from your host, or a server that suddenly runs at 100% CPU: these are classic signs that a PHP or WordPress website has been hacked. After critical bugs like PHP2Shell, it's worth checking even if nothing looks wrong. Many attacks install a hidden backdoor and wait. This guide walks through a practical investigation with copy-paste commands, then shows how to clean up safely.

Checklist for checking whether a PHP or WordPress website was hacked
Most commands below are for Linux servers with SSH access. On shared hosting without SSH, use your host's file manager and malware scanner, and ask support to run the checks for you.

Warning signs

  • Visitors (especially from Google or on mobile) are redirected to spam, gambling or "you won" pages.
  • Google shows Japanese/pharma spam pages under your domain, or Search Console reports Security issues.
  • New admin users you didn't create.
  • Unknown .php files in upload folders, or files with random names.
  • High CPU usage (often crypto-miners) or your host suspends the account for sending spam.

Step 0: Don't destroy the evidence

Before deleting anything, take a copy of the site files, the database and the logs. You'll need them to understand how the attacker got in, and to restore anything you remove by mistake.

TS=$(date +%F)
sudo tar czf ~/site-files-$TS.tgz /var/www/example.com
sudo tar czf ~/logs-$TS.tgz /var/log/nginx /var/log/apache2 /var/log/php* 2>/dev/null
mysqldump -u root -p example_db | gzip > ~/db-$TS.sql.gz

Step 1: Check WordPress core and plugin files

If you use WordPress, WP-CLI can compare every core and plugin file with the official versions. It's the fastest way to find modified files:

cd /var/www/example.com
wp core verify-checksums
wp plugin verify-checksums --all
WP-CLI verify-checksums output showing modified and unexpected files

Any file reported as "doesn't verify against checksum" or "should not exist" needs a closer look. Note: premium plugins from outside WordPress.org can't be verified this way.

Step 2: Find recently changed and suspicious PHP files

# PHP files modified in the last 30 days
find /var/www/example.com -name '*.php' -mtime -30 -printf '%TY-%Tm-%Td %TH:%TM  %p\n' | sort -r | head -50

# PHP files inside upload folders (there should be none)
find /var/www/example.com/wp-content/uploads -name '*.php'

# files containing common backdoor functions
grep -rlE --include='*.php' 'eval\(base64_decode|eval\(gzinflate|eval\(str_rot13|assert\(\$_(POST|GET|REQUEST)|shell_exec\(\$_' /var/www/example.com

Legitimate plugins occasionally use these functions, so a match isn't proof. But code like eval(base64_decode($_POST['x'])) in a file called wp-cache.php inside uploads/ is almost certainly a web shell.

What a typical web shell looks like

<?php
// Found in /wp-content/uploads/2026/10/cache.php
// Takes code from a POST parameter and runs it. Delete files like this.
@eval(base64_decode($_POST['k']));

Step 3: Check users and the database

# WordPress administrators
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

# recently registered users
wp user list --orderby=registered --order=DESC --number=10 --fields=user_login,user_registered

Also look for spam links or scripts injected into posts and options:

wp db query "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%' AND post_status='publish';"
wp option get siteurl
wp option get home

A changed siteurl or home value causes redirects for everyone.

Step 4: Look for persistence

Attackers make sure they can come back. Check scheduled tasks and running processes:

# cron jobs for the web user and root
sudo crontab -l -u www-data
sudo crontab -l
ls -la /etc/cron.d/

# WordPress scheduled events with odd hook names
wp cron event list

# processes and outbound connections run by the web server user
ps -u www-data -o pid,etime,cmd
sudo ss -tunp | grep -E 'php|www-data'

A PHP process holding a connection to an unknown IP, or a process named like kworker under www-data, is a strong sign of compromise.

Step 5: Read the access logs

# POST requests to unusual PHP files (shells are usually called via POST)
sudo awk '$6 ~ /POST/ {print $7}' /var/log/nginx/access.log | grep '\.php' | sort | uniq -c | sort -rn | head -20

# who accessed a suspicious file
sudo grep 'cache.php' /var/log/nginx/access.log*

The first request to a web shell usually shows how it was uploaded: a vulnerable plugin, a stolen password, or a server bug like PHP2Shell.

Cleaning up

  1. Take the site offline or put it in maintenance mode if it's serving malware.
  2. Restore from a clean backup taken before the first malicious change, if you have one. That's safer than hand-cleaning.
  3. Otherwise reinstall WordPress core and every plugin and theme from official sources. Keep only wp-content/uploads (after removing any PHP files) and your database.
  4. Update everything: PHP, WordPress, plugins and themes. Remove plugins you don't use.
  5. Change every secret: hosting, SSH, database and admin passwords, API keys, and the WordPress salts:
wp config shuffle-salts      # logs everyone out
wp user update admin --user_pass="$(openssl rand -base64 24)"
  1. Check Google Search Console > Security issues, request a review once the site is clean, and remove spam URLs with the Removals tool.
  2. Keep watching logs for a few weeks. Attackers often try their old backdoors again.
If the server itself was compromised (root access, unknown system users, modified system binaries), don't try to clean it. Build a new server, restore clean data, and rotate all credentials.

Prevention

  • Keep PHP and your CMS updated. Turn on automatic security updates on your server.
  • Block PHP execution in upload folders. For Nginx:
location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}
  • Use two-factor authentication for admin accounts and SSH keys instead of passwords.
  • Keep daily off-site backups and test restoring them.

Found something suspicious and not sure what it is? Describe it in the comments (don't paste live passwords or full malicious code) and I'll help you identify it.

Zubaer Ahammed

Full-stack & Android developer from Bangladesh. Builds web platforms and apps and writes practical tutorials here. zubaer.com

Comments