WordPress OSINT, maintenance or security needs? Reach out!
TLDWP

WordPress Security Guide

Understanding security exposures and missing headers detected by our scanner. Click any item to learn what it means, why it matters, and how to fix it.

Critical Issues

🦠 Malware Detection

Critical Severity

What We Detect

Our scanner looks for common malware patterns in your site's HTML output:

  • Obfuscated code: eval(base64_decode(...)), eval(gzinflate(...)) - code designed to hide its true purpose
  • Known backdoors: FilesMan, WSO, c99shell, r57shell, b374k - popular hacker tools

Why It Matters

If malware is detected on your site:

  • Your site may be sending spam or hosting phishing pages
  • Visitors could be redirected to malicious sites
  • Google may blacklist your domain
  • Your hosting provider may suspend your account

How to Fix

  1. Don't panic — but act quickly
  2. Take a backup of your current state (for forensics)
  3. Scan with multiple tools: Wordfence, Sucuri SiteCheck, or MalCare
  4. Check recently modified files: find /var/www -mtime -7 -type f
  5. Review wp-config.php for injected code at the top or bottom
  6. Check .htaccess in all directories for redirects
  7. Update everything: WordPress core, themes, and plugins
  8. Change all passwords: WordPress admin, FTP, database, hosting panel
  9. Consider professional help: Sucuri or Wordfence offer malware removal services

💀 Fatal PHP Errors

High Severity

What It Means

Your site is displaying PHP fatal errors publicly. Common examples:

  • Fatal error: Allowed memory size exhausted
  • Fatal error: Cannot redeclare function
  • Parse error: syntax error, unexpected
  • Fatal error: Class 'ClassName' not found

Why It Matters

Publicly visible PHP errors expose:

  • Full server paths: Reveals your hosting structure
  • Plugin/theme names: Helps attackers find vulnerabilities
  • PHP version: Useful for version-specific exploits
  • Function names: Reveals internal code structure

Plus, your site is likely broken for visitors!

How to Fix

  1. Disable debug display in wp-config.php:
    define('WP_DEBUG', false);
    define('WP_DEBUG_DISPLAY', false);
    define('WP_DEBUG_LOG', true); // Log errors instead
  2. Check PHP error log at /wp-content/debug.log
  3. Fix the underlying issue:
    • Memory exhausted → Increase PHP memory limit
    • Class not found → Reinstall affected plugin/theme
    • Syntax error → Revert recent code changes
  4. Set PHP error reporting in php.ini or .htaccess:
    php_flag display_errors Off
    php_flag log_errors On

Exposed Files

Debug Log High Severity

Path: /wp-content/debug.log

What is it?

When WordPress debugging is enabled, PHP errors, warnings, and notices are written to a file called debug.log. This file is meant for developers to troubleshoot issues during development.

Why is it dangerous?

  • Reveals server file paths (helps attackers map your system)
  • Shows which plugins/themes have errors (identifies weak points)
  • May contain database query errors (can expose table structure)
  • Can contain sensitive data logged by poorly coded plugins
  • Signals to attackers that debugging is enabled

How to fix it

Option 1: Disable debugging in wp-config.php:

define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);

Option 2: Block access via .htaccess (Apache):

<Files debug.log>
    Order allow,deny
    Deny from all
</Files>

Option 3: Block access via Nginx:

location ~* debug\.log$ {
    deny all;
}

Option 4: Delete the file if you don't need it:

rm wp-content/debug.log

Error Log High Severity

Path: /error_log or /error.log

What is it?

The PHP error log captures runtime errors from your server. It's similar to debug.log but is created by PHP itself rather than WordPress.

Why is it dangerous?

  • Contains full server file paths
  • May reveal database connection errors with credentials
  • Shows PHP version and configuration details
  • Exposes application logic through stack traces

How to fix it

Move error logs outside the web root in php.ini:

error_log = /var/log/php/error.log

Or block access via .htaccess:

<Files ~ "^error[_\.]?log$">
    Order allow,deny
    Deny from all
</Files>

PHP Info Medium Severity

Common paths: /info.php, /phpinfo.php, /php.php, /i.php

What is it?

A PHP file containing phpinfo() which outputs detailed information about your server's PHP configuration. Often left behind after initial server setup or debugging.

Why is it dangerous?

  • Reveals exact PHP version (allows targeting known vulnerabilities)
  • Shows all loaded PHP modules
  • Displays server paths and environment variables
  • May expose database hostnames and internal IPs
  • Shows email configuration (SMTP settings)

How to fix it

Simply delete the file:

rm info.php phpinfo.php php.php i.php

If you need phpinfo for debugging, protect it:

<Files "phpinfo.php">
    Require ip 127.0.0.1
    Require ip YOUR.IP.ADDRESS
</Files>

Install.php Critical Severity

Path: /wp-admin/install.php

What is it?

The WordPress installation script. On a properly configured site, this should not be accessible after initial setup.

Why is it dangerous?

  • An attacker could potentially reinstall WordPress
  • If database tables are dropped, the installer becomes active again
  • Can be used to create a new admin account
  • Indicates the site may have configuration issues

How to fix it

Block access via .htaccess:

<Files install.php>
    Order allow,deny
    Deny from all
</Files>

Or via Nginx:

location = /wp-admin/install.php {
    deny all;
}

XML-RPC Medium Severity

Path: /xmlrpc.php

What is it?

XML-RPC is a remote procedure call protocol that allows external applications to communicate with WordPress. It was used for features like pingbacks, the mobile app, and remote publishing.

Why is it dangerous?

  • Brute force amplification: Attackers can try hundreds of passwords in a single request
  • DDoS attacks: Can be used in pingback-based DDoS attacks
  • Username enumeration: Reveals valid usernames
  • Most sites don't need it (REST API replaced most functions)

How to fix it

Block access via .htaccess:

<Files xmlrpc.php>
    Order allow,deny
    Deny from all
</Files>

Or disable via plugin or functions.php:

add_filter('xmlrpc_enabled', '__return_false');

Note: If you use the WordPress mobile app or Jetpack, you may need XML-RPC enabled.

Exposed Directories Medium Severity

Common paths: /backup/, /dev/, /staging/, /old/, /test/

What is it?

Directories that are publicly accessible and may contain sensitive files, backups, or development code that shouldn't be exposed to the internet.

Why is it dangerous?

  • Backup folders: May contain database dumps with all your data
  • Dev/staging folders: Often have debugging enabled and weaker security
  • Old folders: May contain outdated, vulnerable WordPress versions
  • Directory listing shows all files to attackers

How to fix it

Disable directory listing in .htaccess:

Options -Indexes

Or remove/protect the directories:

# Delete if not needed
rm -rf /var/www/html/backup/

# Or password protect
<Directory "/var/www/html/backup">
    AuthType Basic
    AuthName "Restricted"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

Security Headers

Security headers are HTTP response headers that tell browsers how to behave when handling your site's content. They add an extra layer of protection against common attacks.

HSTS (Strict-Transport-Security) Medium Severity

What is it?

HSTS tells browsers to only connect to your site via HTTPS, even if the user types http:// or clicks an HTTP link.

Why is it important?

  • Prevents SSL stripping attacks (man-in-the-middle)
  • Protects users on public WiFi
  • Ensures all traffic is encrypted

How to add it

Apache (.htaccess):

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Nginx:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

CSP (Content-Security-Policy) Medium Severity

What is it?

CSP tells the browser which sources of content (scripts, styles, images, etc.) are allowed to load. It's a powerful defense against cross-site scripting (XSS) attacks.

Why is it important?

  • Blocks malicious scripts injected by attackers
  • Prevents unauthorized content from loading
  • Stops clickjacking attempts

How to add it

Start with a report-only policy to test:

Content-Security-Policy-Report-Only: default-src 'self';

Basic production policy:

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';

Note: CSP requires careful configuration. Test thoroughly before enabling.

X-Content-Type-Options Low Severity

What is it?

This header prevents browsers from "sniffing" the content type and interpreting files differently than declared.

Why is it important?

  • Prevents MIME-type confusion attacks
  • Stops browsers from executing uploaded files as scripts

How to add it

Apache:

Header always set X-Content-Type-Options "nosniff"

Nginx:

add_header X-Content-Type-Options "nosniff" always;

X-Frame-Options Medium Severity

What is it?

Controls whether your site can be embedded in frames/iframes on other sites.

Why is it important?

  • Prevents clickjacking attacks
  • Stops attackers from embedding your site in a malicious page

How to add it

Apache:

Header always set X-Frame-Options "SAMEORIGIN"

Nginx:

add_header X-Frame-Options "SAMEORIGIN" always;

Referrer-Policy Low Severity

What is it?

Controls how much referrer information is sent when users click links to other sites.

Why is it important?

  • Protects user privacy
  • Prevents leaking sensitive URLs (e.g., password reset links)

How to add it

Apache:

Header always set Referrer-Policy "strict-origin-when-cross-origin"

Nginx:

add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Permissions-Policy Low Severity

What is it?

Controls which browser features (camera, microphone, geolocation, etc.) your site can use. Formerly known as Feature-Policy.

Why is it important?

  • Limits attack surface by disabling unused features
  • Prevents malicious scripts from accessing sensitive APIs

How to add it

Apache:

Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"

Nginx:

add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

Protection

Proactive security measures that prevent attacks before they reach your WordPress site.

Web Application Firewalls (WAF) Recommended

What is a WAF?

A Web Application Firewall sits between your website and the internet, filtering malicious traffic before it reaches your server. WAFs block common attacks like SQL injection, XSS, and brute force attempts automatically.

Why does this matter for our scans?

Sites protected by a WAF often block our security scanner, which means we can't check for exposures or missing headers. This is actually a good thing! If a WAF blocks our scanner, it would also block malicious bots and attackers trying to find the same vulnerabilities.

Our detection rate would be nearly twice as high without WAFs — but we'd rather see sites protected than exposed. We focus on helping the ~30-40% of sites that don't yet have this layer of protection.

Popular WAF Options

Cloudflare (Recommended for most sites)
  • Free tier available with basic WAF protection
  • Also provides CDN, DDoS protection, and SSL
  • Easy setup — just change your nameservers
  • Pro plan ($20/mo) adds advanced WAF rules

Setup: Sign up at cloudflare.com → Add your site → Update nameservers at your registrar → Enable "Under Attack Mode" if needed.

Wordfence (WordPress-specific)
  • WordPress plugin with built-in firewall
  • Free version includes endpoint firewall
  • Premium ($119/year) adds real-time threat intelligence
  • Also includes malware scanning and login security

Setup: Install plugin → Go to Wordfence → Firewall → Optimize Firewall → Follow the prompts.

Sucuri
  • Cloud-based WAF with malware cleanup service
  • Plans start at $199/year
  • Includes CDN and performance optimization
  • 24/7 security team for incident response
All-In-One WP Security (Free)
  • Free WordPress plugin with basic firewall rules
  • Includes login lockdown and file integrity monitoring
  • Good starting point for budget-conscious sites

Which should you choose?

  • Small sites / blogs: Cloudflare Free + Wordfence Free
  • Business sites: Cloudflare Pro or Sucuri
  • WooCommerce / high-traffic: Cloudflare Business or Sucuri with their CDN
  • Enterprise: Cloudflare Enterprise or dedicated WAF appliance

Quick Win: Enable Cloudflare in 10 Minutes

  1. Go to cloudflare.com and create a free account
  2. Enter your domain and let Cloudflare scan your DNS
  3. Review the DNS records (usually auto-detected correctly)
  4. Update your domain's nameservers at your registrar
  5. Wait for propagation (usually 5-30 minutes)
  6. Enable "Always Use HTTPS" in SSL/TLS settings
  7. Turn on "Bot Fight Mode" in Security settings

That's it — your site now has basic WAF protection, DDoS mitigation, and a global CDN for free.