Written by 1:44 pm Security, WordPress Views: 10

How to Protect Your WordPress Site from Malware and Crypto Miners (Complete Guide)

A practical guide for developers and site owners on hardening WordPress against malware infections and crypto mining scripts – covering server hardening, file monitoring, mu-plugin security, wp-config hardening, malware detection techniques, and signs your site has been compromised.

WordPress malware and crypto miner protection guide - security hardening illustration

Malware attacks on WordPress sites have grown more sophisticated. Today the goal is not always to deface your site or steal passwords – a large share of compromises exist purely to silently mine cryptocurrency using your server CPU and your visitors’ browsers. This guide walks through practical, code-level steps to harden your site, detect infections early, and remove compromised files when the worst happens.


WordPress powers over 43% of the web, making it a high-value target. Crypto mining malware is particularly attractive to attackers because it is persistent, low-profile, and profitable. A compromised server can mine Monero (XMR) for months before anyone notices. Browser-based miners injected into your theme or plugins use visitor CPU cycles, slowing their machines and damaging your brand trust.

The attack vectors are predictable: outdated plugins, nulled themes, weak admin passwords, and misconfigured servers. What makes crypto miners particularly dangerous is that unlike ransomware or data theft, they often leave the site looking completely normal. There are no obvious signs for site visitors, no defacement, and no missing content. The site just runs slower, and the attacker profits quietly in the background.

Common Entry Points Attackers Use

  • Vulnerable plugins: Plugins with known CVEs are targeted within hours of disclosure. The WPScan database lists thousands of vulnerabilities, many exploitable without authentication.
  • Nulled themes and plugins: Pirated software is the most reliable delivery vector for malware – attackers add backdoors before distributing on file-sharing sites.
  • Weak or reused passwords: Credential stuffing attacks try username and password combinations from other data breaches against your wp-login.php.
  • Hosting account compromise: If your hosting control panel is breached, attackers can modify files directly without touching WordPress at all.
  • Supply chain attacks: Plugins or themes with many installations become targets for attackers who compromise the developer account to push malicious updates.

Your wp-config.php is the highest-value configuration file on your server. Beyond the hidden wp-config.php settings most developers miss, a few security constants can dramatically reduce your attack surface before any plugin is activated:

DISALLOW_FILE_EDIT removes the built-in theme and plugin editor from the admin dashboard – eliminating one of the most-abused post-compromise escalation paths. DISALLOW_FILE_MODS goes further: it prevents WordPress from writing to the filesystem at all, blocking plugin installs and automatic updates. Use this only if you manage updates through WP-CLI or your deployment pipeline.

One more constant worth adding: move the WordPress security keys and salts out of wp-config.php and into environment variables if your hosting supports it. This prevents them from being exposed if wp-config.php is accidentally made world-readable, which does happen on misconfigured shared hosting.


File system permissions are the first line of defense. WordPress needs to write to specific directories – but nothing else should be writable by the web server user. Correct permissions prevent attackers from writing malicious files even after gaining partial access. Pair this with htaccess security and performance tweaks to block common exploit patterns at the server level before they reach PHP.

Recommended File Permissions

Location Permissions Rationale
wp-config.php 400 or 440 Read-only, web server should never write to it
/wp-content/uploads/ 755 Web server needs write access for media uploads
/wp-content/plugins/ 755 755 with DISALLOW_FILE_MODS in wp-config.php
/wp-content/themes/ 755 Same as plugins
All PHP files 644 Web server reads, owner writes, no group/other write
All directories 755 Standard traversal permissions

Block PHP execution in the uploads directory. Add a file at /wp-content/uploads/.htaccess with the directive php_flag engine off on Apache servers. Nginx users should add a location block to their server configuration to deny access to any PHP file within the uploads path.

A correctly configured server should never allow PHP execution from the uploads folder. This single rule prevents an entire class of file upload attacks.


Malware detection starts with knowing when files change. The following mu-plugin creates a snapshot of your wp-includes PHP files, then compares against it on each admin load and emails you when anything changes. It is intentionally lightweight – no database writes beyond the initial snapshot file:

Drop this in wp-content/mu-plugins/ and it activates automatically – no plugin activation needed. The first admin page load generates the baseline snapshot. Subsequent loads compare against it. Production tip: use a transient to throttle the comparison to once per hour instead of every admin page load. Add a transient check at the top of the callback and set it after the comparison completes.


Browser-based crypto miners use JavaScript libraries. The signatures are consistent – known mining library domain names appear in your theme JS files, plugin files, or are injected directly into HTML output via a compromised hook. The following mu-plugin scans your active theme and plugins directory for known miner signatures and surfaces an admin notice if anything is found:

This scanner is intentionally simple. It catches the low-hanging fruit – sites that have been mass-compromised with known libraries. Sophisticated attackers obfuscate their scripts, so this is a supplement to proper file monitoring, not a replacement. For deeper scanning, tools like MalCare, Sucuri SiteCheck, or the open-source WPScan can detect more complex obfuscated payloads.

Signs Your Site Is Running a Crypto Miner

  • Visitors complain of slow machines or high CPU usage when on your site
  • Your server CPU spikes without corresponding traffic increases
  • Google Search Console reports malware or deceptive content warnings
  • Browser dev tools show unfamiliar external script domains loading
  • WordPress admin slows down significantly without any recent changes
  • Outbound connections to known mining pool domains in your server access logs
  • Unexpected PHP files in /wp-content/uploads/ or root directory
  • Your hosting provider flags your account for excessive CPU usage or outbound bandwidth

HTTP security headers are the cheapest hardening step available. A well-configured Content Security Policy (CSP) can block browser-based miners from running at all – even if an attacker manages to inject a script tag, the browser will refuse to execute it if the domain is not whitelisted:

The Content Security Policy in the example is deliberately permissive to serve as a starting point. Tighten script-src to remove unsafe-inline once you have a working nonce-based or hash-based CSP for your specific setup. The Strict-Transport-Security header forces HTTPS for 1 year – only enable this after confirming your SSL certificate is stable.

Test your headers after deployment using securityheaders.com or the Mozilla Observatory. Both tools provide letter grades and specific guidance on what each header does and how to improve it. Aim for a B+ or higher on initial deployment and work toward A grade as you tighten the CSP rules over time.


When file monitoring alerts you to a change, you need to triage quickly. The manual approach: compare your WordPress core files against a fresh download from WordPress.org. Any difference in wp-includes or wp-admin is suspicious and should be treated as a compromise until proven otherwise.

Manual Triage Steps

  1. Download a fresh copy of WordPress matching your installed version from the official WordPress releases page
  2. Compare wp-includes and wp-admin directories using WP-CLI core verify-checksums command
  3. Any file not in the official release is either a plugin/theme file or malware – investigate everything unexpected in core directories
  4. Search for common obfuscation patterns: eval with base64_decode, gzinflate, str_rot13, or long hex strings anywhere in PHP files
  5. Check recently modified PHP files – sort by modification timestamp and investigate anything changed in the past 24-48 hours that you did not change yourself
  6. Review wp-config.php for injected code at the top or bottom of the file – malware often hides here as it is loaded on every request
  7. Check all admin users via WP-CLI user list command filtered to administrator role – remove any unknown accounts immediately
  8. After cleanup, change all admin passwords, rotate WordPress security keys in wp-config.php, and invalidate all active sessions

When you confirm a compromise, speed matters. The longer malware runs, the more damage it does, both to your server and to your search engine rankings if Google detects the infection. Follow this ordered playbook to contain, clean, and recover efficiently.

Step 1, Isolate: Take the site offline immediately. The fastest method is renaming your .htaccess file and replacing it with a maintenance redirect, or using your hosting panel’s password-protect feature on the document root. Do not delete files yet, you need them for forensic analysis. If you are on managed hosting, contact support immediately as they may have server-level isolation tools and recent clean backups available.

Step 2, Preserve evidence: Before cleaning anything, create a full backup of the compromised state including the database. This backup is your forensic record, it helps identify the entry point, the scope of the compromise, and whether customer data was accessed. Store it securely offsite, labeled with the date and a note that it contains compromised files. Never restore from this backup; it exists only for investigation.

Step 3, Identify the entry point: Check your server access logs for the timeframe when the first malicious file was modified. Look for POST requests to unusual endpoints, requests to files in the uploads directory with PHP extensions, and requests from IP addresses that made many rapid sequential requests. The entry point determines whether you need to patch a vulnerability, change passwords, or address a hosting-level issue.

Step 4, Clean core files: Reinstall WordPress core using wp core download --force via WP-CLI. This replaces all core files with verified clean copies from WordPress.org. Do not manually edit core files, always replace them entirely. After reinstalling core, run wp core verify-checksums to confirm every file matches the official WordPress release. Any mismatches after a forced reinstall indicate either a corrupted download or an active process re-injecting malicious code in real time, which points to a server-level rootkit that requires your hosting provider’s intervention.

Step 5, Clean plugins and themes: Reinstall all plugins from WordPress.org using wp plugin install --force for each plugin. For premium plugins, re-download from the vendor’s website and upload fresh copies. Delete any plugin or theme you do not actively use, inactive themes and plugins are common hiding places for backdoors because they sit on the filesystem with PHP execution capability but receive no attention from site administrators. Keep only the plugins you actively need and one default WordPress theme as a fallback.

Step 6, Scan the database: Malware sometimes persists in the database, particularly in the wp_options table (look for suspicious entries with encoded values), wp_posts content (injected script tags), and user meta (unauthorized administrator accounts). Search for base64_decode, eval, and script tags with external domains in your database content.

Step 7, Harden and monitor: Apply all the hardening steps from this guide. Change every password, WordPress admin, database, FTP, hosting panel, and any API keys stored in wp-config.php. Regenerate WordPress salts using wp config shuffle-salts which generates cryptographically random values and invalidates all existing login sessions immediately. Set up the file monitoring mu-plugin and schedule weekly checksum verification. Request a Google Search Console review if your site was flagged, Google typically reviews and clears the warning within 72 hours for sites that have thoroughly cleaned the infection. Submit the review only after you are confident the cleanup is complete, as a failed review adds additional waiting time before you can request another one.


The code-only approach above covers the most important hardening steps without adding plugin weight. But for sites without a dedicated developer monitoring them daily, a security plugin adds automated monitoring that most teams cannot replicate manually. Here is when each option makes sense:

Scenario Recommendation
Developer-managed site, CI/CD pipeline, WP-CLI access Code-only approach (this guide) – lighter, no plugin overhead
Client site, limited developer access, non-technical owner Wordfence free – WAF, login protection, file scanner, email alerts
High-traffic site, PCI/GDPR requirements, frequent audits needed Wordfence Premium or Sucuri Platform – real-time threat feeds, SLA support
Agency managing 10+ client sites MainWP + Wordfence or ManageWP Security add-on for centralized monitoring

Security plugins are not a substitute for proper server hardening – they work at the WordPress application layer and cannot compensate for weak file permissions, outdated PHP, or a misconfigured web server. Use them as the monitoring and alerting layer on top of the foundational hardening covered in this guide.


The best defense is a combination of prevention, monitoring, and rapid response. Prevention alone is not enough – sites with perfectly maintained plugins still get compromised through zero-days, hosting-level breaches, and supply chain attacks on plugin authors. The goal is to minimize dwell time: how long a compromise stays undetected. According to security industry data, the average dwell time for malware on compromised websites is 200+ days, meaning most infections run for over 6 months before detection. Every practice below aims to reduce that window from months to hours.

  • Keep WordPress core, themes, and plugins updated – 70% of infections exploit known vulnerabilities with available patches
  • Use a Web Application Firewall (WAF) – Cloudflare free tier or Wordfence block the most common scanning and exploit attempts
  • Enable two-factor authentication for all admin accounts – prevents credential-stuffing attacks from converting to full compromise
  • Run core and plugin checksum verification weekly via server cron using WP-CLI
  • Keep verified, tested backups offsite – not just on the same server. A compromised server means compromised backups stored locally.
  • Monitor outbound connections from your server – miners communicate with mining pool domains. Unusual outbound traffic on non-standard ports is a strong indicator.
  • Limit login attempts and block XML-RPC if you do not use it
  • Audit your installed plugins quarterly – remove anything you do not actively use. An inactive plugin is still a vulnerability.
  • Implement a Content Security Policy (CSP) header that restricts which domains can serve scripts – this blocks browser-based miners even if the injection succeeds at the file level.
  • Use WP-CLI to automate security checks in your deployment pipeline – run wp core verify-checksums and wp plugin verify-checksums as part of every deployment to catch tampering early.

Building a Security Maintenance Schedule

Ad-hoc WordPress security practices are better than nothing, but a scheduled maintenance routine catches problems before they become emergencies. For most WordPress sites, this schedule provides comprehensive coverage without being overwhelming:

Frequency Task Tool
Daily Review server access logs for suspicious patterns Server log analysis or Wordfence live traffic
Weekly Run core and plugin checksum verification wp core verify-checksums via server cron
Weekly Check for available updates and apply them wp plugin update --all on staging first
Monthly Audit admin user accounts and remove unknown entries wp user list --role=administrator
Monthly Review and test backup restoration process Restore latest backup to staging environment
Quarterly Full plugin audit, remove unused plugins and themes Manual review of active and inactive items
Quarterly Review and update security headers securityheaders.com scan
Annually Rotate all credentials including database passwords Update wp-config.php and hosting panel

For agency teams managing multiple client sites, centralize this schedule using a management tool like MainWP, ManageWP, or InfiniteWP. These platforms let you run security scans, apply updates, and audit users across all client sites from a single dashboard. The time investment in setting up centralized management pays for itself after the first client site gets compromised, having a rapid response capability across all managed sites is invaluable when a vulnerability affects a popular plugin that many of your clients use.


Not everything can be handled at the WordPress layer. Some of the most impactful security measures happen at the hosting and server configuration level. These controls reduce the blast radius of any compromise and in some cases prevent attackers from persisting even after initial access. Think of hosting-level protections as the outer perimeter, they stop the majority of automated scanning and brute-force attempts before they ever reach your WordPress application code.

  • Enable ModSecurity or a similar WAF at the server level – catches attacks before they reach PHP
  • Use PHP 8.1+ – older versions have known vulnerabilities and are no longer receiving security patches
  • Disable dangerous PHP functions in php.ini – functions like exec, passthru, shell_exec, system, proc_open, and popen are rarely needed by legitimate WordPress plugins
  • Enable PHP-FPM with separate pools per site on shared/VPS hosting – isolates compromises between sites so one infected site cannot read files from another
  • Configure fail2ban or similar tools to block IPs after repeated 403 and 404 errors from automated scanning tools
  • Restrict SSH access to specific IPs where possible – this single change prevents most brute-force SSH attacks entirely
  • Enable audit logging at the server level – access logs, error logs, and PHP error logs should all be retained for at least 30 days

Protecting WordPress from malware and crypto miners is not a one-time task. It requires layered defenses: hardening the application configuration, monitoring for file changes, blocking known attack patterns with security headers, and maintaining visibility into what is running on your server. The code examples above give you a starting point you can drop in today without any plugin dependencies. Each layer compensates for the others, if an attacker bypasses your WAF, file monitoring catches the intrusion. If file monitoring misses a database injection, your Content Security Policy blocks the malicious script from executing in visitors’ browsers.

The most expensive security measure you will ever pay for is cleaning up a compromised site after the fact. Professional malware removal services charge $200-500 per incident, and the indirect costs, lost revenue during downtime, damaged search engine rankings, eroded customer trust, and potential regulatory fines if customer data was exposed, often exceed ten times the cleanup cost. Investing a few hours in proper hardening upfront is orders of magnitude cheaper than dealing with a mining malware infection that has been running silently for months. Start with wp-config.php hardening and file permission review, then layer in the monitoring mu-plugin and security headers. Each step builds on the last, creating a defense-in-depth strategy that makes your WordPress site a significantly harder target than the millions of unprotected WordPress installations attackers prefer to target.

Part of running a tight WordPress setup is also managing server load. Check out our guide on controlling the WordPress Heartbeat API to stop admin slowdowns for another impactful system-level tweak that reduces unnecessary background server requests without touching your active theme or installed plugins. And if something does go wrong, our WordPress troubleshooting guides can help you diagnose and resolve common issues quickly.

Visited 10 times, 1 visit(s) today

Last modified: March 26, 2026