Malware threats are increasingly common for WordPress sites. Without proper security measures, a single infection can compromise your site, steal data, or cause your site to go offline. This guide provides a complete strategy to proactively secure, detect, and recover from malware on WordPress.
Whether you’re new to WordPress security or looking to strengthen your existing setup, this guide covers everything you need to protect your site.
Step 1: Secure Credentials
Strengthening your credentials is the first step in securing your site.
- Update All Passwords: Use strong, unique passwords for:
- WordPress Admin
- Database
- FTP/cPanel accounts
- Enable Two-Factor Authentication: Many plugins, like Wordfence, offer two-factor authentication for WordPress admin access.
Step 2: Scan for Malware
Use WordPress security plugins to scan for and remove malware.
Install Wordfence or Sucuri and run a full scan. Review the results to identify any infected files.
In WordPress dashboard, go to Plugins > Add New
Search for "Wordfence" or "Sucuri" and install the plugin
Run a full scan to detect malware
Step 3: Set File and Folder Permissions
Restricting file and folder permissions is essential to prevent unauthorized modifications to your WordPress installation. Proper permissions help ensure that only authorized users can make changes, significantly reducing the risk of malware infections.
Recommended File Permissions
- File Permissions:
- index.php:
644
(allows the owner to read and write; others can read) - wp-config.php:
600
(only the owner can read and write; no access for others, protecting sensitive database credentials) - wp-settings.php:
644
(standard permissions for executable PHP files) - wp-load.php:
644
(standard permissions for core WordPress files) - Other PHP files (in root):
644
(standard permissions for other PHP scripts)
- index.php:
- Folder Permissions:
- Directories (including wp-content):
755
(allows the owner to read, write, and execute; others can read and execute) - wp-admin:
755
(to allow access to the admin dashboard without exposing sensitive data) - wp-includes:
755
(necessary for core files and libraries used by WordPress) - uploads directory (inside wp-content):
755
(ensures proper media uploads while restricting unnecessary access)
- Directories (including wp-content):
Commands to Set Permissions
You can use the following commands in the terminal to set the permissions:
# Set file permissions
chmod 644 /home/yourwpsite.com/index.php
chmod 600 /home/yourwpsite.com/wp-config.php
chmod 644 /home/yourwpsite.com/wp-settings.php
chmod 644 /home/yourwpsite.com/wp-load.php
# Set folder permissions
chmod 755 /home/yourwpsite.com/wp-content
chmod 755 /home/yourwpsite.com/wp-admin
chmod 755 /home/yourwpsite.com/wp-includes
chmod 755 /home/yourwpsite.com/wp-content/uploads
Setting Permissions Using FTP Clients like FileZilla
If you prefer using an FTP client such as FileZilla, follow these steps to set permissions:
- Connect to Your Server: Open FileZilla and connect to your server using your FTP credentials.
- Navigate to Your WordPress Directory: Browse to the location of your WordPress installation.
- Right-Click the File or Folder: Locate
index.php
,wp-config.php
, or any directory (likewp-content
). - Select “File Permissions…”: Right-click and choose the “File Permissions…” option from the context menu.
- Set the Numeric Value: Enter the desired permission value (e.g.,
644
for files,755
for folders) and click OK.
Note for VS Code Users
If you are using Visual Studio Code (VS Code) for remote file editing, note that it does not directly support changing file permissions with chmod
. Instead, you need to:
- Open the integrated terminal in VS Code and execute the
chmod
commands to set the appropriate permissions for your files and folders.
By properly setting file and folder permissions, you significantly enhance your WordPress site’s security and reduce the risk of unauthorized modifications that can lead to malware infections.
Step 4: Disable File Editing in WordPress
Prevent file editing from the WordPress dashboard to mitigate the risk of unauthorized modifications. This can be done by adding the following line to your wp-config.php
file:
define('DISALLOW_FILE_EDIT', true);
Important Folders to Restrict Editing
- wp-content/plugins: Prevent unauthorized changes to plugins that could introduce vulnerabilities.
- wp-content/themes: Restrict modifications to theme files, protecting your site’s visual aspects.
- wp-includes: This folder contains core WordPress files, and any changes here can lead to site functionality issues.
- wp-admin: Protect admin scripts from tampering to secure your site’s administrative area.
Step 5: Prevent PHP Execution in Non-Essential Folders
Malware often hides in folders like wp-includes
or uploads
. Prevent PHP execution in these folders with .htaccess
rules to mitigate potential threats.
Add the Following Code:
<Files *.php>
deny from all
</Files>
To make it compatible with Apache 2.4, you should use the Require all denied statement.
<FilesMatch "\.(php)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
Necessary Folders to Protect
- wp-includes: Core WordPress files should not execute any PHP scripts outside of their intended functions.
- wp-content/uploads: Media uploads are a common target for malware; preventing PHP execution here reduces risk.
- wp-content/plugins: Although plugins may need execution, it’s best to restrict scripts not meant to be run directly.
- wp-content/themes: Similar to plugins, restrict direct execution to ensure security.
Placement of Code
Place this code in .htaccess
files within the following directories:
/home/yourwpsite.com/wp-includes/.htaccess
/home/yourwpsite.com/wp-content/uploads/.htaccess
- Optionally, create and place it in
/home/yourwpsite.com/wp-content/plugins/.htaccess
and/home/yourwpsite.com/wp-content/themes/.htaccess
as needed.
Step 6: Monitor index.php for Unauthorized Changes
Monitoring index.php
with auditctl
is a crucial step in detecting unauthorized changes to your WordPress core files. Since index.php
is one of the primary entry points for WordPress, it’s often targeted by malware and malicious actors to inject harmful code or redirect traffic. Setting up tracking for changes to this file can act as an early warning system, allowing you to take action before extensive damage is done.
Why Monitoring index.php is Important
- High-Risk Target for Attackers:
index.php
is a commonly targeted file in WordPress installations. Attackers often modify this file to:- Inject malicious scripts.
- Redirect traffic to phishing sites.
- Create backdoors for ongoing unauthorized access.
- Early Detection of Suspicious Activity: By monitoring
index.php
, you gain the ability to catch suspicious activity as soon as it occurs, rather than after the effects are visible (e.g., site defacement, malware infection). Real-time detection helps in minimizing the impact of an attack. - Tracking the Source of the Attack: One of the most valuable aspects of audit logs is that they reveal which user or process attempted to modify
index.php
. If unauthorized changes occur, you’ll be able to see details like:- User ID: Identifies who or what account initiated the change, helping in tracking any compromised credentials.
- Process and Command Information: Logs the exact command used and the process responsible, revealing whether it’s a script, plugin, or external access.
- Time and Session Details: Helps correlate the attack timing with other site events, narrowing down the source of the breach.
Setting Up Monitoring
Use the following command to tell auditctl
to watch index.php
for any write or attribute changes:
sudo auditctl -w /home/yourwpsite.com/index.php -p wa -k index_change
-w /home/yourwpsite.com/index.php
: Specifies the file path to monitor.-p wa
: Watches for write (w
) and attribute (a
) changes.-k index_change
: Sets a unique key name to easily find these specific audit logs.
Checking for Unauthorized Changes
When you suspect that index.php
may have been altered or at regular intervals, check the audit logs for changes.
- Use the following command to search the audit logs for changes to
index.php
:
- Use the following command to search the audit logs for changes to
sudo ausearch -k index_change
- This command filters the logs based on the
index_change
key you defined earlier, displaying all logged changes toindex.php
.
Understanding the Log Output
Each log entry provides specific details about the monitored event. Here’s an example of what a typical log entry might look like:
----
time->Tue Nov 5 15:16:50 2024
type=PROCTITLE msg=audit(1730819810.011:6967472): proctitle=617564697463746C002D77002F686F6D652F796F75727770736974652E636F6D2F696E6465782E706870002D70007761002D6B00696E6465785F6368616E6765
type=SYSCALL msg=audit(1730819810.011:6967472): arch=c000003e syscall=44 success=yes exit=1108 a0=4 a1=7fff8bbdb660 a2=454 a3=0 items=1 ppid=1265253 pid=1265254 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts3 ses=586174 comm="auditctl" exe="/usr/sbin/auditctl" key="index_change"
Here’s what each part means:
- Time: When the change occurred.
- Process Title: Command-line argument (in hexadecimal) used by the process that caused the event.
- System Call:
- Architecture: System architecture (e.g.,
x86_64
). - Syscall: ID of the syscall (e.g.,
sendmsg
). - Result: Indicates the syscall was successful.
- Exit Code: Further context on the syscall’s result.
- Architecture: System architecture (e.g.,
- Parameters: Internal parameters, relevant for debugging.
- File Affected: Shows the number of items involved (just
index.php
here). - Process IDs: Parent process and process ID.
- User and Group IDs: Show the user account (root) involved.
- Terminal and Session IDs: Information about the terminal and session, useful for correlating other events.
- Command and Executable: The command and executable path that triggered the event.
- Audit Rule Key: The specific key to filter relevant logs.
Benefits of Monitoring index.php
- Immediate Threat Detection: You can detect malicious changes as they happen, giving you an opportunity to investigate before an attack progresses.
- Accountability: Identifies who or what process made changes, so you can quickly isolate compromised credentials or vulnerabilities.
- Audit Trail for Incident Response: By maintaining a detailed log of changes, you have a valuable audit trail that can assist in both preventing future attacks and identifying weaknesses in your security setup.
By monitoring index.php
with auditctl
, you gain visibility into unauthorized attempts to change core WordPress files, helping protect your site from potentially severe consequences. This level of tracking not only alerts you to unauthorized changes but also helps pinpoint the exact process and user responsible, enabling you to respond more effectively.
Step 7: Make index.php Immutable
Prevent any modifications to index.php
by making it immutable:
chattr +i /home/yourwpsite.com/index.php
To allow changes again, use:
chattr -i /home/yourwpsite.com/index.php
To check if the immutable attribute is set, use lsattr:
lsattr /home/yourwpsite.com/index.php
----i--------- /home/yourwpsite.com/index.php
(The i indicates that the file is immutable.)
Step 8: Check Recent File Modifications
Use find
to check for recently modified files, which may indicate malware activity.
find /home/yourwpsite.com -type f -mtime -1
List files that set chattr +i
find /home/yourwpsite.com -type f -exec lsattr {} + | grep '^[^ ]*i'
List files that set chattr +i (in current directory)
find ./ -type f -exec lsattr {} + | grep '^[^ ]*i'
List files and directories that set chattr +i
find /path/to/search -exec lsattr {} + 2>/dev/null | grep '^[^ ]*i'
Benefits of Using chattr
Applying chattr +i
to a directory protects all files and subdirectories contained within. Here are the key benefits:
- Comprehensive Protection: All files and subdirectories inherit the immutable property, preventing any modifications.
- Prevents Accidental Deletion: Safeguards critical files from accidental deletions or modifications.
- Enhances Security: Adds a robust layer of security against unauthorized changes, even for root users.
- Consistency of Application Data: Ensures that configuration and data files remain unchanged, leading to stable application performance.
- Protection Against Malicious Modifications: Safeguards sensitive data from unauthorized changes in multi-user environments.
- Ease of Recovery: Makes it easier to recover the intended state of the system after a failure, as all files remain intact.
- Effective for Backup Directories: Prevents changes to backup files, ensuring they remain usable for restoration.
Step 9: Search for Suspicious Code in Files
Malware often includes functions like eval
or base64_decode
. Use grep
to search for these in your files:
grep -rE "(eval|base64_decode|exec|shell_exec|system|assert)" /home/yourwpsite.com
Step 10: Restrict wp-admin Access by IP
Add this to .htaccess
in the wp-admin
folder to limit access by IP:
<Files *>
order deny,allow
deny from all
allow from [Your IP Address]
</Files>
Step 11: Password Protect wp-admin Directory
Add another layer of security to wp-admin
by enabling password protection:
- Use Directory Privacy in cPanel or create an
.htpasswd
file with:
htpasswd -c /home/yourwpsite.com/.htpasswd username
Step 12: Add a Web Application Firewall (WAF)
Implement a WAF, like Cloudflare or Sucuri, to block malicious traffic before it reaches your site.
Benefits of a WAF:
- Block known bad IPs
- Prevent automated bot attacks
- Detect malicious behavior and block threats
Step 13: Regular Monitoring Routine
Create a schedule for reviewing logs and security settings:
- Weekly: Review file changes, check logs, and update plugins.
- Monthly: Full malware scan and theme/plugin update check.
Step 14: Keep WordPress, Themes, and Plugins Updated
Keeping your WordPress installation and plugins up-to-date is essential for patching vulnerabilities. Set automatic updates for plugins and themes whenever possible.
Step 15: Use Offsite Backups for Recovery
Regularly back up your site to an offsite location. This ensures you can quickly restore your site if malware strikes.
- Scan Backups Before Restoring: Always scan the backup for malware before restoring.
Quick Security Checklist
Here’s a quick checklist to regularly secure your WordPress site:
- Updated all passwords and enabled two-factor authentication.
- Scanned for malware with a security plugin.
- Set restrictive file and folder permissions.
- Disabled file editing in
wp-config.php
. - Made
index.php
immutable. - Regularly check for suspicious activity with
auditctl
andgrep
. - Implemented a Web Application Firewall (WAF).
Troubleshooting Common Issues
- Permissions Errors: Double-check permissions in cPanel’s File Manager if you encounter issues.
- Audit Rule Setup: If
auditctl
monitoring isn’t working, ensureauditd
is running on your server. - Firewall/WAF Issues: Adjust firewall settings if legitimate traffic is being blocked.
Summary of Commonly Targeted Files
Certain files are often targeted by malware due to their critical roles in WordPress functionality and security:
- wp-config.php: Stores database credentials and configuration settings. If compromised, it can give attackers full access to your database and site.
- .htaccess: Controls redirects and URL structures. Malware often manipulates this file to hijack traffic or redirect visitors to malicious sites.
- index.php: Serves as the main entry point for WordPress. Attackers frequently target this file to inject harmful scripts, redirect users, or create backdoors for continued access.
- wp-settings.php: This file is responsible for setting up the WordPress environment. If compromised, attackers can manipulate core functionalities.
- wp-load.php: This file is used to bootstrap the WordPress environment. Attackers may exploit it to load malicious code.
- functions.php: Part of the active theme, this file can be manipulated to execute arbitrary PHP code, potentially giving attackers unauthorized access to your site.
- php.ini: This configuration file for PHP can be targeted to change settings that might weaken security, allowing for further exploitation.
- wp-includes/: While not a single file, the entire
wp-includes
directory contains core WordPress files that, if altered, can change the behavior of the site or introduce vulnerabilities. - uploads/: The media upload folder can also be targeted, especially if it’s misconfigured, allowing attackers to upload malicious files disguised as images or documents.
By being aware of these commonly targeted files, you can take proactive measures to secure them and reduce the risk of malware infections on your WordPress site.
Conclusion
By following the steps in this guide, you can secure your WordPress site against malware and detect any unauthorized changes before they become major issues. Regular monitoring, strong credentials, and a layered security approach are essential for ongoing site security.
Stay proactive, stay secure, and keep WordPress malware-free!