Here’s a scary truth I’ve seen more than once in the field: a WordPress site can look “normal” and still be compromised. When the attacker hits the database only, file scanning can come back clean while your site starts serving junk pages, injecting spam users, or redirecting visitors. In 2026, this is still one of the most common ways small business sites get hit because it blends in with normal content changes.
Database-only compromises are exactly what they sound like: the web server files stay untouched, but the MySQL/MariaDB database is altered. If you only check your plugins and theme files, you’ll miss the real problem.
This guide is written for real cleanup work. You’ll learn how to scan your WordPress database, how to restore safely (without breaking your live site), and how to lock things down so it’s harder for the same attacker to come back.
What is a Database-Only Compromise in WordPress, and how does it happen?
A database-only compromise is when attackers change WordPress data (users, posts, options, and sometimes scripts stored in fields) without needing to rewrite PHP files on disk. WordPress reads almost everything from the database, so small changes can cause big site behavior.
Common entry points are weak logins, leaked admin passwords, outdated plugins, or stolen admin sessions. After they get in, attackers often keep their footprint small. They may:
- Create hidden admin users with odd usernames.
- Change wp_options values to store redirect code or remote URLs.
- Modify wp_posts with spam content that appears only to visitors from certain countries or devices.
- Inject JavaScript or links into places that look like normal “content,” like post content, custom fields, or widget text.
- Add cron jobs or scheduled events that keep reinfecting the site.
One more detail that matters: many malware scanners focus on filesystem changes. If the attacker never touches files, those scanners will often show “no threats found.”
Quick reality check: when your filesystem looks clean but the site is hacked
Use these signs to confirm you should investigate the database first. I’ve used this exact checklist on emergency cleanups because it saves time.
- Your website shows new redirects, but there are no suspicious files in
/wp-content. - Google Search Console reports hacked content even though your theme files didn’t change.
- New admin users appear, but your FTP/SFTP change logs show nothing.
- Comments/posts look normal to you, but some visitors see spam pages.
- Security plugins show “nothing to remove,” yet the behavior continues after you clear caches.
Quick test: check your server access logs for login spikes and your WordPress “last changed” timestamps. If the server files are unchanged but database-backed content shifts, you’re in database-only territory.
If you want a broader view of file-based cleanups too, our post on WordPress incident response for malware cleanup walks through the first 60 minutes after you suspect a hack.
Scan your WordPress database like a pro (without breaking anything)

Before you run any checks, copy the database and switch into safe mode. You don’t scan a live database if you can avoid it, because heavy queries can slow down production.
Step 1: create a full backup
Export your database using your host’s tools (cPanel, Plesk, or phpMyAdmin) or a command line dump. Then also back up WordPress files.
Example (if you have shell access):
mysqldump -u dbuser -p --databases your_db_name > backup_$(date +%F).sql
Step 2: confirm your table prefix
WordPress usually uses wp_, but many sites use a different prefix for basic hardening. You’ll need it for all checks.
Look for tables like *_options, *_users, *_posts, *_postmeta, and *_usermeta.
Check wp_options for suspicious settings (the #1 place I find trouble)
Most database-only hacks leave footprints in wp_options. WordPress stores plugin settings, site URLs, and other important switches there.
Run targeted queries for obvious malware patterns. In real incidents, I’ve searched for:
base64,eval,gzinflate,str_rot13iframe,document.write,script- Remote URLs or strange domains
- Suspicious function names often used in webshell-style drops
Example queries (adjust table prefix):
SELECT option_name, option_value
FROM wp_options
WHERE option_value LIKE '%base64%'
OR option_value LIKE '%eval%'
OR option_value LIKE '%document.write%'
OR option_value LIKE '%iframe%'
LIMIT 200;
If your site uses lots of legitimate scripts, you may see false positives. That’s okay. The point is to find “needs a closer look” rows fast.
What most people get wrong: they copy the entire options table from a backup without thinking. If the site had real changes after the last clean backup, you can roll back good content and lose work. Instead, remove the bad pieces while keeping the rest.
Search wp_posts and wp_postmeta for spam content and hidden scripts
WordPress hacks often hide spam in posts, pages, and post meta. Attackers like to store spam as normal content types so it blends in.
Start by looking for unusual post types and strange titles. Then scan content fields.
SELECT ID, post_type, post_status, post_title, post_date
FROM wp_posts
WHERE post_status IN ('publish','pending','draft','private','future')
ORDER BY post_date DESC
LIMIT 200;
Then search for code-like strings inside content columns. In many setups, the content is stored as post_content and meta values contain extra payloads.
SELECT ID, post_type, post_status, post_title
FROM wp_posts
WHERE post_content LIKE '%<script%'
OR post_content LIKE '%<iframe%'
OR post_content LIKE '%base64%'
OR post_content LIKE '%eval%'
LIMIT 200;
For meta, do:
SELECT meta_id, post_id, meta_key, LEFT(meta_value, 200) AS preview
FROM wp_postmeta
WHERE meta_value LIKE '%http%'
AND meta_value LIKE '%%'
LIMIT 200;
That meta query example is intentionally broad. In practice, you’ll refine it to specific keywords you find during your first pass.
Inspect users and usermeta for hidden admin accounts
If the attacker got access, they usually create an extra admin user so they can return later. A database-only compromise often includes new entries in wp_users and wp_usermeta.
Look for accounts created at odd times, accounts you don’t recognize, and accounts with admin capabilities.
SELECT ID, user_login, user_email, user_registered
FROM wp_users
ORDER BY user_registered DESC
LIMIT 200;
Then check user roles. Roles and capabilities are stored in usermeta:
SELECT um.user_id, u.user_login, um.meta_key, um.meta_value
FROM wp_usermeta um
JOIN wp_users u ON u.ID = um.user_id
WHERE um.meta_key IN ('wp_capabilities','wp_user_level')
LIMIT 200;
Experience note: in one incident last year, the “admin” user had a login name that looked like a normal support account. The email was real, but the role list had extra capabilities that didn’t match any plugin we used.
Check cron and scheduled events for reinfection loops
WordPress stores scheduled tasks in the database. Attackers use this to keep re-adding bad options, creating new posts, or changing redirect rules.
Check tables like:
wp_optionsfor cron-related keys likecron- Event-related tables if your plugin uses custom schedules
If you see entries with suspicious payloads, you need to remove both the schedule and the bad target values.
Restore your WordPress data safely: clean, partial, or full rollback?

Restoring is where many sites fail. The goal is to remove the bad data without undoing your whole business. That means choosing the right restore method for what happened.
Here are the three restore approaches I use, in order of preference.
Option A: selective rollback (best when you have a clean backup close to the incident)
Selective rollback means you restore only the infected rows or only specific tables/records. This keeps your real content and settings that weren’t affected.
Example workflow:
- Compare suspicious
wp_optionsrows between the backup and today. - Restore those rows only, and leave the rest.
- Delete any malicious post records or meta rows you found.
- Remove unauthorized user accounts and reset roles for legit users.
I prefer this because it reduces “collateral damage.” But it requires careful checking and a good backup from the right time.
Option B: table-level restore (fast when you have a known clean snapshot)
Table-level restore is when you replace whole tables like wp_posts or wp_options from a backup. This is quicker than row-by-row work, but it can erase legitimate content created after the backup time.
Typical table targets for database-only cleanup:
wp_optionswp_postsandwp_postmetawp_usersandwp_usermeta
Important: never restore tables blindly. If your legitimate site updates run daily, a full table restore can roll back new offers, updated service pages, or recent blog posts.
Option C: full database rollback (only when you’re sure the blast radius is huge)
Full rollback means replacing the entire database with a backup. I recommend it when:
- Multiple tables are corrupted.
- The site shows unpredictable behavior across pages.
- You can’t trust the current state at all.
If you do full rollback, follow up with a thorough scan again. Attackers sometimes reinfect within minutes if the vulnerability isn’t fixed yet.
Also, keep your WordPress files consistent with the database restore. Even if the incident started as “database-only,” file changes can happen after the attacker regains access later.
Secure your WordPress database after cleanup: stop the next login and the next reinfection
Cleaning the database removes today’s mess. Securing it stops the attacker from returning and rewriting the same tables.
In 2026, the most effective security steps are boring and direct. Here’s what I do first.
Lock down admin access (this prevents 80% of repeats)
Attackers win by guessing passwords or reusing stolen credentials. Fix the access layer.
- Force all users to reset passwords.
- Remove unknown admin accounts immediately.
- Turn on two-factor authentication (2FA) for every admin user.
- Limit login attempts using your security plugin or web server rules.
- Block XML-RPC if you don’t use it (or require stronger protection).
If your server supports it, enable rate limiting at the web server (Nginx/Apache) or use a WAF from a provider like Cloudflare. I’m not saying “one tool fixes it.” I’m saying you stack defenses so one failure doesn’t become a breach.
Harden wp-config.php and WordPress keys
wp-config.php is where WordPress connects to your database. This file is also a common target because it can reveal connection details.
Do these:
- Confirm file permissions are correct.
- Regenerate WordPress salts/keys in
wp-config.php. - Use a strong database user password and remove any “shared” credentials.
Regenerating salts helps break stolen session cookies. It won’t fix the database data by itself, but it blocks the “still logged in” problem.
Apply database-level protections that actually matter
Your WordPress database should not be open to the internet. It usually isn’t, but check anyway.
At minimum:
- Restrict database user privileges to only what WordPress needs.
- Disallow remote database connections unless you truly need them.
- Turn on and review database audit logs if your host offers them.
Also, make sure backups are protected with access controls. A backup that anyone can download is just another leak.
Verify plugins and themes, even if you started with “database-only”
This is the part that surprises people: attackers may keep a backdoor in a plugin setting stored in the database, but the plugin itself might be compromised too. So you still need file-level checks.
Use a plugin integrity checker, and compare plugin/theme versions to the vendor sources. If you’re not sure, wipe and reinstall only after database cleanup is complete.
Our malware removal guides pair well with this step. See our post on WordPress hardening tips after a cleanup for the exact settings we verify before we declare a site “safe.”
People Also Ask: database-only hacks in WordPress
How do I know if my WordPress hack is in the database?
You suspect a database-only hack when site behavior changes but plugin/theme files don’t. Typical clues are new admin users, altered options like siteurl/home, spam pages that appear in search, and redirects without obvious file changes.
Another strong sign is when scanners that check file hashes report clean results, but Search Console flags “infected” content. That usually means the harmful code is stored in database fields.
Can a malware scanner miss a database-only WordPress compromise?
Yes. Many scanners focus on file signatures, file changes, and known malicious PHP files. If the attacker injected scripts into wp_posts or changed options in wp_options, a file scanner can miss it.
That’s why I always scan the options, posts, and users tables during cleanup—especially when files look untouched.
Should I restore my WordPress database or re-install everything?
If your files are truly clean and the damage is only in the database, a database restore or selective rollback is usually faster. If you suspect a plugin/theme infection on disk, re-installing or re-uploading clean copies of those files makes sense too.
In practice, you often do both: restore the database and then verify file integrity. This avoids the “fixed the database, but the plugin reinfects it” loop.
Is it safe to delete wp-content if only the database was hacked?
Not in most cases. Deleting wp-content is disruptive because it contains your uploads, themes, and plugins. If your files are clean, removing them adds new risk and work.
A better approach is targeted file verification, reinstallation of only the suspicious plugins/themes, and full database cleanup/restore.
Real-world example: what a database-only cleanup looks like
One client I helped in early 2026 had “no malware found” from their usual scanner. The site still showed a strange redirect for mobile users, and Search Console flagged hacked content.
When we pulled the database, the options table had rows referencing a remote script hosted on a domain that didn’t match their niche. The suspicious value was stored inside a plugin setting. The plugin files on disk were unchanged, which is why the file scan missed it.
Our fix was selective rollback of the affected wp_options values, deletion of a spam post stored in wp_posts, removal of a hidden admin in wp_users, and then password resets + 2FA enablement. After we closed the access hole, the redirects stopped within minutes.
Cost-wise, the cleanup took about 2.5 hours of focused work and a couple hours of verification and monitoring after. If the site had required full database rollback, it would’ve been longer and risked losing recent blog drafts.
Verification checklist before you put the site back online
Don’t declare victory until you prove the site is stable. Here’s my go/no-go checklist after a database-only compromise cleanup.
- All admin accounts are known and roles match what you expect.
- No suspicious
wp_optionsvalues remain (URLs, eval/base64 patterns, hidden iframe tags). - No spam posts/pages are present in
wp_postsor linked in menus. - Scheduled tasks (cron) don’t keep re-adding bad values.
- Site behavior is tested from mobile and desktop.
- Google Search Console no longer shows “hacked” alerts after re-indexing.
- You review auth logs for login attempts from the attacker’s likely IP range.
If you’re using a maintenance window, keep it short. If your site is business critical, stage the fix on a staging environment, then push changes quickly.
Also, keep an eye on performance. Some “cleaning” steps accidentally leave broken caching or broken plugin settings, and that can cause downtime later.
Conclusion: the safest path is database-first scanning, targeted restoring, and access hardening
Database-only compromises are dangerous because they hide in plain sight. The safest recovery plan is to back up first, scan wp_options, wp_posts, and user tables, then restore only what’s infected. After that, lock down logins with password resets, 2FA, and stricter access rules so the attacker can’t rewrite your WordPress data again.
If you want help with malware cleanup and WordPress security incident recovery, we provide expert support for small business sites. And if you’re already cleaning after a detected issue, pair this guide with our related resources like WordPress hardening tips after cleanup and WordPress incident response for malware cleanup to cover both the database and the access side.
Featured image alt text: Database-only compromise cleanup steps for scanning and restoring WordPress data safely