Cleaning a hacked website without losing your content is entirely possible if you work methodically, back up everything before making changes, and understand exactly what the attacker modified. Most website owners recover fully within a few hours to a couple of days by following a structured process. This guide walks you through every stage, from the moment you discover the breach to hardening your site so it is not compromised again.

What Are the First Signs Your Website Has Been Hacked?

Before you can clean anything, you need to confirm you are actually dealing with a hack and understand its scope. Attackers rarely announce themselves, so look for these indicators:

  • Google Safe Browsing warnings — Google Search Central flags sites distributing malware or engaging in deceptive practices. You may see a "This site may be hacked" notice in search results.
  • Unexpected redirects — Visitors are sent to spam, gambling, or pharmaceutical sites.
  • Strange new files or folders — Unknown PHP, JavaScript, or .htaccess files appear in your file manager.
  • New admin accounts you did not create — A classic sign of a privilege escalation attack.
  • Defaced pages or injected content — Spammy links, foreign-language text, or pop-ups embedded in your pages.
  • Your hosting provider suspended your account — Hosts routinely scan for malware and suspend offending accounts.
  • Alerts from your security plugin or Google Search Console — Search Console sends email notifications when it detects hacked content.

If you see any of these, do not panic and do not immediately delete things. Follow the steps below in order.


Step 1: Put Your Site Into Maintenance Mode Immediately

Taking your site offline for visitors while you work prevents further harm — both to your visitors (who could be exposed to malware) and to your SEO standing (Google penalises sites that actively serve malicious content).

  • Use your hosting control panel or a maintenance-mode plugin to display a simple "Back soon" page.
  • If your host suspended your account, contact support and explain you are actively cleaning the site — many hosts will grant temporary access for exactly this purpose.
  • Do not simply delete files at random yet. You need a clear picture first.

Step 2: Back Up the Compromised Site — Yes, Even Now

This feels counterintuitive, but backing up the infected site before you touch anything is critical.

Why back up an infected site?

  1. It preserves your database, media uploads, themes, and plugins — the content you want to keep.
  2. It gives you a forensic copy so you can study what the attacker changed.
  3. If you accidentally delete legitimate files, you have something to restore from.

How to take a backup right now

  • Via your hosting control panel (cPanel/Plesk): Use the Backup Wizard or File Manager to download a full account backup (files + database).
  • Via SSH: Run tar -czf backup_infected.tar.gz /path/to/your/site and download it locally.
  • Via your CMS backup plugin: Tools like UpdraftPlus (WordPress), Akeeba Backup (Joomla), or Drush (Drupal) can export files and database together.

Store this backup somewhere completely separate — a local drive or a cloud account the attacker cannot reach. Label it clearly as "infected — do not restore without cleaning."


Step 3: Identify Exactly What Was Compromised

Rushing to delete files before you understand the attack scope is the number-one cause of accidentally removing legitimate content.

Run automated malware scans

  • Sucuri SiteCheck (free, online): Paste your URL and it checks for blacklisting, malware signatures, and injected content visible from the outside.
  • MalCare, Wordfence, or iThemes Security (WordPress plugins): These scan files on your server and flag suspicious code, unfamiliar files, and changed core files.
  • ClamAV via SSH: Run clamscan -r /path/to/your/site --log=scan_results.txt for a server-side scan.
  • Your hosting provider's malware scanner: Many shared hosts include Imunify360 or SiteLock in the control panel.

Check file modification dates

Attackers often inject code into recently modified files. In your file manager, sort files by "last modified" date. Files changed on a date you did not make updates are suspicious.

Via SSH:

find /path/to/your/site -type f -name "*.php" -newer /path/to/reference_file.php

Replace reference_file.php with a file you know was last touched on your most recent legitimate update.

Check your database for injected content

Log in to phpMyAdmin (or use a MySQL client via SSH) and search for common attack strings in your database tables:

sql SELECT * FROM wp_posts WHERE post_content LIKE '%<script%'; SELECT * FROM wp_options WHERE option_value LIKE '%eval(%';

(Adjust table prefixes for your CMS.)

Common injection strings to search for: eval(base64_decode, document.write, iframe src, <script src=, and hacked by.

Review server access logs

Your raw access logs (usually in ~/logs/ or /var/log/apache2/) show exactly which IP addresses accessed which files and when. Look for:

  • Repeated POST requests to unusual PHP files (often uploaded web shells)
  • Requests to wp-login.php, xmlrpc.php, or admin/index.php from foreign IPs in rapid succession (brute force)
  • Access to files in /tmp/ or /uploads/ that should not be executable

Step 4: Restore Clean Core Files Without Touching Your Content

Your content lives in your database and your uploads/media folder. Your CMS core files, themes, and plugins do not contain your posts, pages, images, or customer data — so you can safely replace them.

For WordPress sites

  1. Download a fresh copy of WordPress from WordPress.org — match your current version exactly.
  2. Replace core files: Upload and overwrite everything in /wp-admin/ and /wp-includes/. Also overwrite the PHP files in the root (like wp-login.php, wp-cron.php, etc.), but do not overwrite wp-config.php and do not touch wp-content/ yet.
  3. Verify wp-config.php: Open this file and check it for injected code at the very top or bottom. It should start with <?php and nothing else before it.
  4. Reinstall plugins: Deactivate and delete every plugin, then reinstall them from WordPress.org or from your legitimate purchase downloads. Do not restore plugins from your infected backup.
  5. Reinstall themes: Do the same for themes. If you have a custom child theme, compare it line-by-line against a clean parent theme to identify injected code before restoring it.

For Joomla sites

  1. Download a fresh Joomla package matching your version from Joomla.org.
  2. Overwrite the core directories (/administrator/, /components/, /libraries/, /modules/, /plugins/, /templates/system).
  3. Preserve /templates/ (your custom template) and /images/ (your media), but scan them carefully.
  4. Reinstall all third-party extensions from their original sources.

For Drupal sites

Use Drush: drush pm-update drupal redownloads core. Check the Drupal Security Team advisories at drupal.org/security for any known exploits affecting your version.

For custom-built or static sites

Compare every file against your version-controlled repository (Git, SVN). If you do not use version control, now is the time to start. Diff tools like diff -r clean_copy/ infected_site/ will highlight every changed line.


Step 5: Clean Your wp-content (or Equivalent) Folder

This is where your uploads, themes, and plugins live — and where attackers love to hide malicious files because it is writable by the web server.

Uploads folder

  • Your /wp-content/uploads/ folder should contain only images, PDFs, videos, and other media files. It should never contain .php files.

  • Run this command via SSH to find PHP files hiding in your uploads directory:

    find /path/to/wp-content/uploads/ -name "*.php" -type f

    Delete every result. Legitimate WordPress functionality never places PHP files in uploads.

  • Also check for files with double extensions like image.jpg.php or document.pdf.php.

.htaccess file

The .htaccess file in your site root is a common target. Attackers inject redirect rules that send mobile users or visitors coming from Google to spam sites. Open it and compare it against a fresh WordPress .htaccess:

BEGIN WordPress

RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] # END WordPress

Everything outside those markers that you did not put there deliberately is suspicious.


Step 6: Clean the Database

Your database holds your posts, pages, user accounts, comments, and site settings. Attackers inject malicious JavaScript or SEO spam links directly into this content.

  1. Export a fresh database dump via phpMyAdmin (Export → SQL format) so you have a clean starting point to reference.

  2. Search and replace suspicious strings: Use a tool like the WP-CLI search-replace command or the "Better Search Replace" plugin to find and remove injected scripts.

    wp search-replace '<script src="http://malicious.example.com' '' --all-tables

    Be precise with your search terms to avoid accidentally breaking legitimate content.

  3. Audit user accounts: In phpMyAdmin, check your wp_users table (or equivalent). Delete any accounts you do not recognise, especially those with administrator privileges.

  4. Check the options table for injected code: In WordPress, run:

    SELECT option_name, option_value FROM wp_options WHERE option_value LIKE '%eval%';
    
    
  5. Reset all passwords stored in the database — see Step 8.


Step 7: Find and Close the Entry Point

Cleaning without closing the door means you will be hacked again within hours. OWASP (the Open Web Application Security Project) identifies the most common entry points as:

  • Outdated software: An unpatched CMS, plugin, or theme with a known CVE (Common Vulnerability and Exposure).
  • Weak or reused passwords: Brute-forced admin credentials.
  • Nulled (pirated) themes and plugins: These almost always contain backdoors intentionally.
  • Compromised FTP/SSH credentials: Your hosting account credentials were stolen, likely via malware on your own computer.
  • Insecure file permissions: World-writable files (777 permissions) allow anyone on a shared server to modify your files.
  • SQL injection or cross-site scripting vulnerabilities in custom code.

How to identify your specific entry point

  • Check server logs for the first appearance of malicious files — note the date, IP, and request method.
  • Check whether your CMS or any plugin had a known vulnerability announced around that date (search the CVE database at cve.mitre.org or WPScan Vulnerability Database for WordPress).
  • Scan your own computer for malware — your FTP credentials could have been stolen by a keylogger.

Step 8: Change Every Credential and Revoke All Sessions

Once the site is clean, assume every password and key associated with it is compromised.

  • CMS admin password: Change it to a randomly generated password of at least 20 characters.
  • Database password: Update it in both your database management panel and your wp-config.php (or equivalent config file).
  • FTP/SFTP credentials: Change these in your hosting control panel.
  • Hosting account password: Change your cPanel/Plesk/hosting dashboard password.
  • SSH keys: Revoke any existing authorised keys and generate new ones.
  • WordPress secret keys: Replace the AUTH_KEY, SECURE_AUTH_KEY, and related constants in wp-config.php using the WordPress Secret Key Generator at api.wordpress.org/secret-key/1.1/salt/. This logs out all currently logged-in users and invalidates stolen session cookies.
  • Email account passwords: Especially the email address used for your admin account.

Enable two-factor authentication (2FA) on every account that supports it.


Step 9: Fix File Permissions

Incorrect file permissions are both a cause and an enabler of hacks. CISA (the Cybersecurity and Infrastructure Security Agency) consistently recommends the principle of least privilege — give files and directories only the permissions they need to function.

For most web servers running WordPress or similar CMSs:

Location Recommended Permission
Directories 755 (rwxr-xr-x)
PHP and config files 644 (rw-r--r--)
wp-config.php 600 (rw-------)
.htaccess 644 (rw-r--r--)

Set these via SSH:

find /path/to/your/site -type d -exec chmod 755 {} ; find /path/to/your/site -type f -exec chmod 644 {} ; chmod 600 /path/to/your/site/wp-config.php

Never set any file or directory to 777 on a live server.


Step 10: Bring the Site Back Online and Request a Review

Before you go live, run one final scan using Sucuri SiteCheck or your security plugin to confirm no malware signatures remain.

Remove Google's blacklist warning

If Google flagged your site, you must request a manual review:

  1. Log in to Google Search Console.
  2. Navigate to Security & Manual Actions → Security Issues.
  3. Review the listed issues and confirm you have resolved each one.
  4. Click Request Review and describe in detail what you found and what you fixed.

Google Search Central documentation states that review requests are typically processed within a few days to a few weeks, depending on the severity and history of the site.

If your site is listed on other blacklists (check via Sucuri SiteCheck, which queries over 65 databases), each provider has its own delisting process, but most will automatically remove your site within 24–72 hours once Google clears it.

Announce the return

If your site serves a community or regular customers, a brief, honest update builds trust. You do not need to share technical details — a simple "We identified and resolved a security issue and have strengthened our defences" is sufficient.


Step 11: Harden Your Site to Prevent Reinfection

Cleaning a hack is only half the job. OWASP's proactive controls and CISA's guidelines both emphasise that prevention is far cheaper than recovery.

Essential hardening steps

  • Keep everything updated: CMS core, all plugins, all themes — on the day updates are released, not weeks later. Most hacks exploit known vulnerabilities that already have patches available.

  • Delete unused plugins and themes: Every inactive plugin is an attack surface. If you are not using it, remove it entirely.

  • Install a web application firewall (WAF): A WAF like Cloudflare (free tier available) or Sucuri's firewall blocks malicious requests before they reach your server.

  • Enable a security plugin: Wordfence, Sucuri Security, or iThemes Security provide file integrity monitoring, login protection, and real-time threat intelligence.

  • Limit login attempts: Brute force protection is built into most security plugins. Lock out IPs after 3–5 failed login attempts.

  • Disable XML-RPC if you do not use it (WordPress): This endpoint is a common brute force and DDoS vector. Add this to your .htaccess:

    Order Deny,Allow Deny from all
  • Move your admin login URL (WordPress): Plugins like WPS Hide Login change /wp-admin/ to a custom URL, drastically reducing automated attacks.

  • Use HTTPS: Ensure your SSL certificate is valid and force all traffic to HTTPS. Your hosting provider or Cloudflare can handle this.

  • **Set up automated daily back