WordPress - Why is WP Super Cache creating suspicious cache folders

The symptom is rather ominous, your wp-content/cache/supercache folder is suddenly populated by additional domain name folders having no connection to your website. What could have caused this? Has your website been compromised or is there some reasonable explanation for this behavior.

After migrating my blog to https a few weeks ago, which included doing some configuration changes, I got to experience this issue first hand. My supercache folder was populated with a few new domain folders containing index-https.html and index-https.html.gz. I diffed these files against my “original and validated” index files and they all checked out. The cached content was still generated from my home page, but why did WP Super Cache create a new folder with a different domain name.

# Content from /wp-content/cache/supercache (truncated)
drwxr-xr-x 11 4096 Feb  9 19:47 blog.paranoidpenguin.net/
-rw-r--r--  1    0 Jan 23 08:30 index.html
drwxr-xr-x  2 4096 Feb  3 12:47 this-is-not-mine.com/
drwxr-xr-x  2 4096 Feb  9 18:47 not-mine-either.com/

By comparing the timestamps originating from the new unwanted folders against the web server’s access log, I found the requests that had initiated the process. Unfortunately, those requests would reveal nothing as they simply contained the following:

# access_log (truncated)
1.2.3.4 - - [10/Feb/2016...] "GET / HTTP/1.1" 200 38702
1.2.3.4 - - [10/Feb/2016...] "GET / HTTP/1.1" 200 38702

I’m also running ModSecurity in an aggressive configuration and would have expected it to pick up on any suspicious requests, but it had kept quiet. This indicated that there were no malicious payload involved, but I decided to load the Apache module mod_log_forensic to log all client requests regardless. I should then be able to spot any potential misconfiguration that had caused WP Super Cache’s unwanted behavior.

Meanwhile I studied the .htaccess rules generated by WP Super Cache as I’m using the mod_rewrite functionality. Below is the rewrite condition that checks if a supercached file is already available for the page requested. If that is the case, then the rewrite rule serves it.

# .htaccess (heavily truncated)
RewriteCond ...%{SERVER_NAME}/$1/index-https.html -f
RewriteRule ^(.*) "...%{SERVER_NAME}/$1/index-https.html" [L]

This caught my attention as I know from experience that you should never rely on the ServerName directive as that value could be supplied from the client under some circumstances.

My immediate conclusion was that a client had spoofed the host header and thus fooled WP Super Cache to go ahead and create a new folder based on the fake host. While working on the issue I also got a hit in my forensic log that confirmed my suspicions (notice the host value).

# forensic_log (actual malware domain removed)
+Vroi738AAAEAABBUhpkAAABD|GET / HTTP/1.1|Host:www.****wh.com|User-Agent:Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)|Accept:*/*
-Vroi738AAAEAABBUhpkAAABD

How to block requests containing invalid or spoofed hosts:

# Block hosts not matching server name
RewriteCond %{HTTP_HOST} !^blog\.paranoidpenguin\.net$ [NC]
RewriteRule ^(.*)$ - [L,R=403]

The above rule will deny any clients (by returning 403 Forbidden) that doesn’t address the correct host. That includes clients simply using the server IP address (bots, seo scanners, misbehaving crawlers, shodan, shadowserver, and on and on..). The HTTP_HOST variable should match the servername of your virtual host.