What a WordPress Security Audit Actually Involves

A WordPress security audit goes beyond running a vulnerability scanner. It is a systematic manual review of the actual security state of your site, examining the configuration, access controls, file integrity, and server-level settings that attackers look for when targeting WordPress installations. Most compromises happen through known vulnerabilities in outdated plugins, weak credentials, or misconfigured file permissions. This guide covers the specific checks to perform on a WordPress site to identify the vulnerabilities that are most likely to be exploited.

Performing a WordPress security audit requires access to the WordPress admin panel, your hosting control panel, and in some cases, direct server access via SSH. Before making any changes to a live site, it is worth creating a full backup including both files and the database. If you are unsure about modifying configuration files or permissions, working with an IT specialist who offers website maintenance services can help ensure the audit is carried out safely.

Why Regular Audits Matter

WordPress sites face constant automated attacks. Bots scan the internet looking for vulnerable installations, and many compromise attempts are opportunistic rather than targeted. A plugin with a known security flaw that has not been updated will be found and exploited regardless of how small or obscure your site may seem.

Regular audits also help catch configuration drift. Over time, updates, new plugins, and server changes can introduce new vulnerabilities or leave old ones exposed. A quarterly review cycle is practical for most business sites, with additional checks whenever a plugin, theme, or the WordPress core is updated.

Checking for Outdated Plugins and Themes

Outdated plugins remain the primary attack vector for WordPress sites. Securing WordPress installations properly means keeping all components current. Every plugin that has not been updated in the last 30 days should be reviewed. Check the last update date on the Plugins page in wp-admin. Any plugin showing a warning that it has not been tested with the current WordPress version is a priority update.

Run this SQL query against the WordPress database to list all active plugins with their versions:

SELECT option_value FROM wp_options WHERE option_name = 'active_plugins';

Decode the PHP serialised array and cross-reference each plugin version against the WordPress plugin repository changelog to see if a security patch has been released since the installed version. If a plugin has not been updated in over 90 days and shows no recent development activity, consider replacing it with a maintained alternative.

Delete plugins and themes that are installed but not in use. Inactive plugins are still exploitable if they contain vulnerabilities, because their files remain accessible on the server even if they are not loaded by WordPress. Each unused plugin is an additional attack surface that serves no purpose on your site.

Reviewing User Accounts and Privileges

List all WordPress user accounts with a direct database query:

SELECT user_login, user_email, display_name FROM wp_users;

Check for accounts using the username "admin", "administrator", or the site domain name. These are the first targets for brute force attacks. If found, create a new account with Administrator privileges and delete the default admin account. Make sure the new administrator account uses a strong, unique password and a different email address.

Check for accounts with the Administrator role that belong to people who no longer work at the organisation. Compromised accounts are a common entry point for WordPress attacks, and orphaned administrator accounts represent an ongoing risk. Remove accounts that are no longer needed, or downgrade their role to Subscriber if the user still needs access for some purpose.

Enforce strong passwords for all accounts. The password for each account should be at least 16 characters, unique, and stored as a hashed value. If your hosting provides it, enable two-factor authentication for all Administrator accounts. This adds a significant layer of protection even if a password is compromised through other means.

Inspecting the wp-config.php File

The wp-config.php file contains database credentials, authentication keys, and security salts. These settings control fundamental aspects of your site's security posture. When auditing this file, check that the following conditions are met:

  • Database credentials are strong and unique: They should not be the default values from installation. If your hosting uses automated WordPress installers that set up predictable credentials, change them immediately.
  • Authentication unique keys and salts are present and long random strings: If they are the default placeholder values from installation, anyone who knows them can generate a valid logged-in session cookie. WordPress provides a secure key generator you can use to create new values.
  • WP_DEBUG is set to false in production: Leaving debug mode on exposes file paths, database query errors, and potentially code snippets in error messages. These details help attackers map your site's structure.
  • DISALLOW_FILE_EDIT is set to true: This disables the built-in theme and plugin file editor in wp-admin, which prevents an attacker with an admin account from modifying PHP files directly through the WordPress dashboard.

Here are the recommended configuration directives for a production WordPress site:

define('DISALLOW_FILE_EDIT', true);
define('WP_DEBUG', false);
define('FORCE_SSL_ADMIN', true);

Checking File Permissions

Incorrect file permissions are a common WordPress security issue that often goes unnoticed. The web server runs as a specific user, and files and directories should be accessible to that user but not writable by the web server process for sensitive files.

The correct permissions for most WordPress files are 644, which means the owner can read and write while others can only read. Directories should use 755, allowing the owner full access while others can read and execute but not write. The exceptions that require special attention are:

  • wp-config.php should be 600: This makes it readable only by the owner. Even the web server user should not be able to read this file directly.
  • The wp-content/uploads directory should be 755: The web server needs to write to it for uploaded files, but you should prevent PHP execution within this directory.
  • Any .htaccess files should be 644: These configuration files should not be writable by the web server.

Check permissions recursively using the following commands:

find /var/www/html -name "wp-config.php" -exec stat -c "%a %n" {} \;
find /var/www/html/wp-content/uploads -type d -exec stat -c "%a %n" {} \;

If any files are writable by the web server user that should not be, correct them with these commands:

chmod 600 /var/www/html/wp-config.php
chmod 644 /var/www/html/.htaccess

It is worth checking whether your hosting environment uses the correct owner for WordPress files. Some shared hosting setups use a different group for the web server user, which can create permission conflicts or security gaps depending on the configuration.

Scanning for Malware and Backdoors

WordPress backdoors are often disguised as legitimate WordPress files or hidden in theme functions. Attackers use backdoors to maintain access even after you remove the original compromise. Common backdoor patterns include base64-encoded strings in PHP files, eval calls with variable contents, files named after WordPress core files but placed in unexpected locations, and PHP files in the uploads directory.

Search for suspicious patterns in theme and plugin files using these commands:

grep -r "eval(" /var/www/html/wp-content/themes/ --include="*.php"
grep -r "base64_decode" /var/www/html/wp-content/plugins/ --include="*.php"
find /var/www/html/wp-content/uploads -name "*.php" -type f

Any PHP file in the uploads directory is almost certainly a backdoor. WordPress never places PHP files in uploads, but compromised sites often have them uploaded through a plugin or theme vulnerability. If you find any, investigate immediately before assuming they are harmless.

Use a malware scanner such as Wordfence or Sucuri to perform a deep scan of all files. These tools maintain signatures of known backdoor patterns and can identify suspicious modifications to core WordPress files. Keep in mind that no scanner catches everything, and a manual review of unusual files often finds what automated tools miss.

Reviewing the Access Log for Attack Patterns

The web server access log contains a record of every request made to your site. Reviewing it reveals automated attack attempts that may not have succeeded yet but indicate your site is being actively targeted. Look for these patterns:

  • Requests to wp-login.php with POST methods: Repeated POST requests with common username strings such as "admin" or "Administrator" indicate brute force login attempts.
  • Requests to xmlrpc.php with repeated POST attempts: This is the WordPress XML-RPC brute force attack vector, and attackers increasingly use it to bypass login rate limiting.
  • Requests to non-existent PHP files: Automated vulnerability scanning often targets files that do not exist, revealing what tools are being used against your site.
  • Requests to wp-admin from a range of source IPs: Distributed brute force attacks use many different IP addresses to bypass simple IP-based rate limiting.

A basic check for failed login attempts using nginx logs:

grep "wp-login.php" /var/log/nginx/access.log | grep "POST" | awk '{print $7}' | sort | uniq -c | sort -rn | head

If XML-RPC is not needed by any of your plugins or integrations, disable it. Add the following to your site .htaccess file:

# Block WordPress XML-RPC
<FilesMatch "xmlrpc.php">
Order Deny,Allow
Deny from all
</FilesMatch>

For Apache servers, reviewing access logs regularly helps identify ongoing attacks. Consider setting up automated alerting for unusual patterns, such as a sudden spike in requests to login pages or admin areas.

Checking for SSL and Mixed Content Issues

Verify that the site forces HTTPS and does not serve mixed content. Mixed content occurs when HTTPS pages load resources such as images, scripts, or stylesheets over HTTP. This breaks the security indicator in browsers and can allow man-in-the-middle attacks on individual resources.

In wp-config.php, ensure these directives are set:

define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);

Check for hardcoded HTTP URLs in the database that would cause mixed content warnings:

SELECT * FROM wp_posts WHERE post_content LIKE '%src="http://%';

Update any HTTP URLs to HTTPS, or use protocol-relative URLs where practical. Many browsers now flag mixed content as a security issue, and search engines may downgrade sites that serve insecure resources on otherwise secure pages.

If you are considering your hosting setup, it is worth noting that cheap hosting can introduce additional security risks beyond configuration issues, including shared server vulnerabilities and inadequate monitoring.

Auditing the Database Prefix

If the WordPress database table prefix is the default wp_, automated SQL injection attacks can target the known table names. Check the prefix in wp-config.php:

$table_prefix = 'wp_';

If the prefix is the default, change it to something unique such as wpx7k_ or yoursite_. This requires modifying the database tables and all references in the WordPress configuration. Several security plugins can handle this migration, but the change must be made before the site is live and before any compromise has occurred. Attempting to change the table prefix on a site that is already under attack or already compromised is unlikely to resolve the underlying problem.

Checking the Web Server Configuration

WordPress security depends partly on the web server settings that control how requests are handled. If your site runs on Apache, reviewing the server configuration helps identify settings that may be too permissive. Apache security settings such as disabling directory listing, restricting access to sensitive files, and enabling appropriate security headers all contribute to a harder target.

For nginx-based setups, similar principles apply. Ensure that PHP processing is restricted to the WordPress document root and that access to configuration files is blocked at the server level. The following nginx configuration snippet blocks direct access to wp-config.php:

location ~* wp-config.php {
    deny all;
}

Moving Forward After the Audit

A WordPress security audit reveals the vulnerabilities that attackers actually exploit. Focus on outdated plugins and themes, weak or default credentials, misconfigured file permissions, backdoors in uploads directories, exposed debug modes, and attack patterns in access logs.

Once you have completed the audit, address high-priority issues first and document your findings. Set a schedule for regular reviews, and establish a process for checking new plugin installations before adding them to your site.

WordPress security is not a one-time configuration. It requires ongoing attention as the threat landscape changes and new vulnerabilities are discovered in the plugins and themes you depend on. If you need help reviewing your current setup, you can get in touch with details of your site and what you want to improve.