Secure Vulnerable WordPress Files and Directories

Recently Jason A. Donenfeld reported a simple vulnerability in W3 Total Cache on the Full Disclosure mailing list, which was picked up by the Security Ledger website, and then posted on Slashdot. The vulnerability is a simple Apache Httpd configuration oversight — plugins often create their own folders under ./wordpress/wp-content/ without considering that directory indexing might be turned on, or that files within that folder are located under a DocumentRoot, and thus available to anyone. Some configuration files are also vulnerable in this way — the wp-config.php file, for example. During the WordPress install, it is recommended that the wp-config.php be re-located one folder above ./wordpress/, to move it out of the DocumentRoot.

Plugins generally create two types of “cache” folders; one that a PHP script uses as a kind of temporary database — W3 Total Cache and most caching plugins work this way — or a folder that holds generated content accessible by URLs, like resized images, etc. We could configure the web server to deny access to all folders named “cache” — this would be fine for PHP scripts that serve-up cached files themselves — but this would break other plugins (like NextGEN Gallery) which create content in a cache folder that is then accessible by URLs.

Along with using a plugin like BulletProof Security to secure my WordPress websites, I also include the following Apache Httpd configuration in all my WordPress virtualhosts:


# protect wp-config.php and other config files
<FilesMatch "^(wp-config.php|advanced-cache.php|db-config.ini|db.php|object-cache.php)">
	Order deny,allow
	Deny from all
	Satisfy all
</FilesMatch>

# protect cache content and BPS backup files
<DirectoryMatch "^.*/wordpress/wp-content/(cache|widget-cache|bps-backup|plugins/bwp-minify/cache|plugins/db-cache-reloaded-fix/cache|w3tc/dbcache)/.*">
	Order deny,allow
	Deny from all
	Satisfy all
</DirectoryMatch>

# prevent execution of php files from the upload folder
<DirectoryMatch "^.*/wordpress/wp-content/uploads/.*">
	php_flag engine off
	AddType text/plain .php
</DirectoryMatch>

# provide all files under uploads/crayon/ as plain text
<DirectoryMatch "^.*/wordpress/wp-content/uploads/crayon/.*">
	ForceType text/plain
</DirectoryMatch>

There are generally two approaches to security; deny everything, and allow some things specifically, or allow everything and deny some things specifically. The example above takes the second approach — we deny access to specific cache folders and files we want to protect. Another solution would be to deny access to all folders with the word “cache” in their names (as an example), followed by additional rules to allow access to “cache” folders we know have content that needs to be accessed directly by URLs.

Since I’ve mentioned BulletProof Security, I should also mention that it can be a little touchy to install and maintain. It doesn’t like other plugins messing with it’s .htaccess file, and it tends to block a few essential files and directories. I use the following rules in it’s “Custom Code -> CUSTOM CODE PLUGIN FIXES” option:

# NextGEN Gallery Cache
RewriteCond %{REQUEST_URI} ^/wp-content/gallery/cache/
RewriteRule . - [S=16]

# Facebook extra query info
RewriteCond %{QUERY_STRING} fb_action_ids=[0-9]+&fb_action_types=.* [NC]
RewriteRule . - [S=15]

# Allow access to wp-cron.php, etc.
RewriteCond %{REQUEST_URI} ^/(wp-cron|checkip)\.php
RewriteRule . - [S=14]

# Allow css and js (with query strings)
RewriteCond %{REQUEST_URI} ^.*\.(css|js)$
RewriteRule . - [S=13]
Find this content useful? Share it with your friends!