The wp-config.php file is the single most sensitive file in any WordPress installation. It holds the database hostname, database name, username, and password in plain text alongside the secret authentication keys and salts that sign user session cookies, the database table prefix, and any custom environment constants you have defined. If an attacker reads this file through a direct browser request, they have everything they need to connect to your database, extract all content, and take full control of the site. In a normal configuration PHP processes the file before Apache returns a response, so a direct HTTP request to wp-config.php returns a blank page rather than raw file contents. But this protection depends on PHP being active and correctly mapped to that path — a misconfigured server or a PHP engine failure can break that assumption entirely. Defense in depth means not trusting PHP as your sole protection for such a critical file. Apache’s .htaccess Files directive lets you deny all HTTP requests to a specific filename at the web server level, before any PHP code runs. This block applies unconditionally regardless of PHP status and adds a second independent layer of protection. Beyond wp-config.php, the xmlrpc.php endpoint has been a persistent attack target for years: brute-force login campaigns use its system.multicall method to test thousands of password combinations in a single HTTP request, and botnet operators exploit it as a DDoS amplification vector. If you don’t use the XML-RPC protocol — which is required only by older mobile apps, some Jetpack features, and certain remote posting tools — blocking it entirely eliminates a meaningful attack surface. You can also protect the .htaccess file itself from being read directly, which prevents information leakage about your URL rewrite rules. All three rules fit neatly into the existing WordPress .htaccess file below the default permalink rewrite block.
Problem: Direct HTTP access to wp-config.php and xmlrpc.php poses a security risk on Apache-based servers.
Solution: Add the following rules to the .htaccess file in your WordPress root directory:
# Block direct HTTP access to wp-config.php
<Files wp-config.php>
order allow,deny
deny from all
</Files>
# Block direct access to .htaccess itself
<Files .htaccess>
order allow,deny
deny from all
</Files>
# Block xmlrpc.php if you do not use it
<Files xmlrpc.php>
order allow,deny
deny from all
</Files>
NOTE: These directives apply to Apache only. On Nginx, use a location block with deny all; for the same effect. On Apache 2.4 and newer, the preferred modern syntax is Require all denied instead of the order allow,deny + deny from all pair — both work, but newer syntax is recommended on updated servers. After editing .htaccess, immediately reload the site in a browser to confirm it responds normally — a syntax error in .htaccess causes a 500 error for all requests until corrected.