Website defaced or showing unauthorized content: what to check first
For site owners who suddenly see hacked text, spam pages, strange redirects, or content they did not publish. This runbook helps you confirm whether the problem is in your CMS, hosting, DNS, CDN cache, or source code, then apply the safest fix and verify the site is clean.
TL;DR — If your site suddenly shows content you did not publish, first put the site in maintenance mode or behind a temporary password, then check the admin users, recent file changes, and DNS records. The single most common fix is removing a malicious admin/plugin or restoring known-good files from backup, then rotating passwords and API keys so the attacker cannot come back. Reading time: ~6 min
The scenario
It is a normal Tuesday afternoon. A client sends a screenshot of your homepage promoting crypto, gambling, or a fake browser update you definitely did not add. You open the site and sometimes it looks normal for you, but on another device it redirects to a spam page, or only some URLs are affected. Now you need to answer two questions fast: is the content coming from your website itself, or from DNS/CDN (content delivery network, a cache/proxy in front of your site), and how do you stop it without making things worse?
Symptoms
- The homepage or a few pages show spam, political text, casino links, fake download buttons, or a message like "Hacked by ..."
- Search results show pages you never created, often with URLs like
/cheap-pills,/viagra,/casino,/best-seo-offer - Visitors report redirects to another site, but you do not always see it yourself
- Your CMS (content management system) has unknown admin users or recent posts you did not publish
- Source files contain unfamiliar code such as:
<?php eval(base64_decode('...'));
- Web server logs show requests to admin or upload paths from unusual IPs, for example:
POST /wp-login.php 200
POST /xmlrpc.php 200
POST /administrator/index.php 200
- DNS records point to an IP address or nameserver you do not recognize
- The origin server looks clean, but the public site still shows the bad content
- Search Console or browsers warn about malware, phishing, or deceptive pages
Likely causes
| Cause | How common | Quick check |
|---|---|---|
| CMS admin account, plugin, or theme was compromised | Very common | In your CMS admin, open Users/Admins and Plugins/Extensions; look for unknown admins or recently changed plugins |
| Malicious files were uploaded or core files were modified on the server | Very common | In your hosting file manager, sort public_html or web root by Last Modified descending |
| DNS was changed to point the domain somewhere else | Common | In your provider dashboard (e.g. domain registrar: DNS/Nameservers), compare A/AAAA/CNAME/nameservers to your documented values |
| CDN or cache is serving injected content | Common | Open the origin directly by temporary origin URL or server IP/hosts-file test and compare it to the public domain |
| Source code or deployment pipeline was compromised | Less common | In your Git host, check the latest commits and deployment history for unknown changes |
| Database content was altered directly | Less common | In your CMS admin, review recent posts/pages/widgets/menus for unknown edits |
Step-by-step diagnosis
- Contain first: put the site behind maintenance mode or a temporary password. In your hosting or site dashboard, use the maintenance mode feature if available; otherwise ask your agency/host to place basic auth (username/password prompt) in front of the site.
⚠️ This can cause temporary downtime for visitors, but it limits harm while you investigate.
This is your problem if: the bad content is public and being indexed or shared.
Jump to: continue to step 2 after containment.
- Check whether DNS points where you expect. Open your domain registrar or DNS provider dashboard and review the domain's Nameservers and DNS records. Compare them to your documented values or your hosting provider's expected records.
This is your problem if: nameservers changed recently, or the A/AAAA/CNAME records point to an unfamiliar destination.
Jump to: Fixes → DNS was changed to point the domain somewhere else
- Compare the public site to the origin site. In your hosting dashboard, find the server IP or temporary origin URL. Open that directly, or ask support for the origin hostname. If the public domain is bad but the origin is clean, the issue is likely CDN/cache or DNS.
This is your problem if: origin is clean but the public domain is defaced.
Jump to: Fixes → CDN or cache is serving injected content
View as text
[Visitor Browser] ---- 1. GET public domain ----> [CDN/DNS]
| |
| 2. compare content | 3. fetch origin
v v
[Public Site] [Origin Server]- Check CMS admins and extensions. Log in to your CMS and review:
- Users/Admins
- Plugins/Extensions/Modules
- Appearance/Themes
- Scheduled posts or content blocks/widgets
This is your problem if: you find an unknown admin user, a plugin/theme you did not install, or a recently modified extension around the time of the incident.
Jump to: Fixes → CMS admin account, plugin, or theme was compromised
- Check recent file changes in the web root. In your hosting control panel, open File Manager and sort by Last Modified. Look in common paths such as
/public_html,/www,/htdocs,/wp-content/uploads,/wp-content/plugins,/app,/public.
This is your problem if: you see recently changed PHP/JS files you did not deploy, files with random names, or hidden files like .ico, .cache, .well-known containing code that does not belong.
Jump to: Fixes → Malicious files were uploaded or core files were modified on the server
- Check deployment history and Git commits. In your Git provider and deploy dashboard, review the latest commits, who pushed them, and whether any deploy happened without your team expecting it.
This is your problem if: there are unknown commits, force-pushes, changed build secrets, or a deploy from an unfamiliar user/token.
Jump to: Fixes → Source code or deployment pipeline was compromised
- Check content stored in the database. In your CMS admin, review recent edits to pages, posts, menus, widgets, and SEO fields. If your host provides phpMyAdmin or a database browser, inspect recent rows in content tables.
This is your problem if: the unwanted text/links exist in the CMS editor or database, while theme files look clean.
Jump to: Fixes → Database content was altered directly
Fixes
CMS admin account, plugin, or theme was compromised
- Remove unknown admin users in your CMS admin.
- Disable and remove suspicious plugins/themes from the dashboard.
- Update the CMS core, all plugins, and all themes.
- Rotate all passwords: CMS admins, hosting panel, database, SFTP/FTP, and email accounts used for password resets.
- Turn on MFA (multi-factor authentication) if your CMS or host supports it.
If you have WP-CLI (WordPress command line), these commands help:
wp user list --role=administrator
wp plugin list
wp theme list
wp plugin deactivate suspicious-plugin
wp user delete badadmin --reassign=1
wp core update
wp plugin update --all
wp theme update --all
Verify it worked: log out, log back in, confirm only expected admins remain, and reload the affected page in a private/incognito window.
Malicious files were uploaded or core files were modified on the server
- Restore the site files from the last known-good backup in your hosting dashboard.
- If you cannot restore the whole site, replace core application files from a clean release package and remove unknown files.
- Check writable upload folders for executable files like
.php,.phtml, or unexpected.js.
⚠️ Restoring files can overwrite legitimate recent changes. If possible, download a copy of the current site first for evidence.
Common checks if you have shell access:
find public_html -type f -mtime -7 | sort
find public_html -type f \( -name "*.php" -o -name "*.phtml" \) | grep "/uploads/"
grep -R "base64_decode\|eval(" public_html
If using WordPress with WP-CLI:
wp core verify-checksums
Verify it worked: the modified file list now matches your expected deploy, and the defaced content no longer appears after a hard refresh.
DNS was changed to point the domain somewhere else
- In your registrar or DNS provider dashboard, restore the correct nameservers and DNS records.
- Remove unknown DNS records, especially A, AAAA, CNAME, URL redirect, and TXT records related to verification you do not recognize.
- Lock the domain if your registrar offers registrar lock / transfer lock.
- Rotate the registrar account password and enable MFA.
A command-line check from your computer:
dig +short yourdomain.com A
dig +short yourdomain.com AAAA
dig +short NS yourdomain.com
Verify it worked: dig returns the expected IPs/nameservers and the public site resolves to your real host after DNS propagation.
CDN or cache is serving injected content
- In your CDN or proxy dashboard, purge the full cache.
- Review page rules, workers/functions, edge redirects, and custom HTML/JS injection settings; disable anything unfamiliar.
- If needed, temporarily bypass the CDN by switching the DNS record from proxied to DNS-only, if your provider supports that model.
- Rotate CDN API tokens and remove unknown team members/integrations.
A simple header check:
curl -I https://yourdomain.com
Look for cache-related headers such as cf-cache-status, x-cache, or via.
Verify it worked: the public domain now matches the origin content and stays clean after a purge and several reloads.
Source code or deployment pipeline was compromised
- Revert to the last known-good commit in Git.
- Review recent commits, deploy hooks, CI/CD secrets, and service accounts.
- Rotate repository access tokens, deploy keys, and environment secrets.
- Trigger a clean rebuild/redeploy from the trusted commit.
Example Git commands:
git log --oneline --decorate -n 20
git revert <bad_commit_sha>
git push origin main
Verify it worked: the deployed artifact matches the trusted commit and no unauthorized deploys appear in the deployment history.
Database content was altered directly
- Remove the malicious pages/posts/widgets/menus in the CMS admin.
- Restore the affected database tables or records from backup if many entries were changed.
- Rotate database credentials and CMS admin passwords.
- Audit forms, file uploads, and vulnerable plugins that may have allowed the write.
If you have database access, export suspicious rows before changing them:
mysqldump -u USER -p DBNAME wp_posts wp_options > suspicious-content-backup.sql
Verify it worked: site search and page source no longer contain the unwanted text/links, and the CMS revision history shows only expected content.
Prevention
- Add file change monitoring on the web root. If your host supports alerts, watch for changes under the web root except deploy windows. On Linux servers, a simple baseline check can be scheduled:
find /var/www/html -type f -exec sha256sum {} \; > /root/site-baseline.sha256
sha256sum -c /root/site-baseline.sha256
- Turn on MFA everywhere that can change the site. Do this for the domain registrar, DNS/CDN, hosting panel, Git provider, and CMS admins. Start with the registrar and hosting accounts first; those are the highest-impact accounts.
- Block script execution in upload folders. For Apache, place this in the uploads directory
.htaccessif your app allows it:
<FilesMatch "\.(php|phtml|php5|phar)$">
Require all denied
</FilesMatch>
For nginx, add a deny rule for upload paths in your server config.
- Pin and scan dependencies in CI before deploy. Example GitHub Actions step:
- name: Install dependencies
run: npm ci
- name: Audit high severity issues
run: npm audit --audit-level=high
- Keep a documented "known-good" record of DNS and admins. Store the expected nameservers, A/AAAA/CNAME values, CMS admin list, and CDN account owners in your password manager or internal docs so you can compare quickly during an incident.
- Back up both files and database daily, and test restore monthly. A backup is only useful if you can restore it fast. Keep at least one copy off the server itself.
This article was written by an AI system and published pending human review. Verify anything you intend to act on.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI