One of the most common hacker techniques on WordPress sites is to find a plugin that has a vulnerability, and use that plugin to upload an initial malware file onto your site. The hackers would then access the malware file directly (bypassing WordPress) to install any malware they want, and/or access your database. Hackers know the most common place plugins would put files is in your WordPress wp-content/uploads/ folder. You must Block executing files in your wp-content folder.

There are folders such as wp-content/plugins/ and wp-content/themes/ where you should allow files to execute (or your plugins and theme won’t work). You could even get more specific, and enable just the folders that each plugin specifically uses. However, that is more maintenance work for you; let a top security plugin (WordFence) take care of that for you.

You Must Protect Your Uploads Folder

This is a serious security issue. One reason you must do plugin updates frequently, is plugin authors (well, the good ones, at least) will patch security issues as soon as anyone informs them. That’s because there are security people who check the hacker’s bulletin boards for issues the hackers are bragging about, and alert the plugin authors.

Here is an example of the kind of hacker junk you would see if your security software were capturing the information:

errorstatuserrortriggerrequriquerystringuseragentcookiesallowheaderspostvariables
403badRequestString:wpcontent/wp-content/plugins/work-the-flow-file-upload/public/assets/jQuery-File-Upload-9.5.0/server/php/index.php Mozilla/5.0 (Windows NT 6.1; rv:34.0) Gecko/20100101 Firefox/34.0 Accept: */* Accept-Encoding: gzip, deflate–31aa900beb174efa942c7958119e7885
Content-Disposition:_form-data;_name–>”action”upload
–31aa900beb174efa942c7958119e7885
Content-Disposition: form-data; name=”files”; filename=”wp-classes.php”
Content-Type: text/plain–31aa900beb174efa942c7958119e7885–
403badRequestString:wpcontent/wp-content/plugins/work-the-flow-file-upload/public/assets/jQuery-File-Upload-9.5.0/server/php/index.php Mozilla/5.0 (Windows NT 6.1; rv:34.0) Gecko/20100101 Firefox/34.0 Accept: */* Accept-Encoding: gzip, deflate–f2ee98a757e94b9897a2c9b1a9ffa74f
Content-Disposition:_form-data;_name–>”action”upload
–f2ee98a757e94b9897a2c9b1a9ffa74f
Content-Disposition: form-data; name=”files”; filename=”wp-classes.php”
Content-Type: text/plain
–f2ee98a757e94b9897a2c9b1a9ffa74f–

What Do These Columns Mean?

ErrorStatus 403 means “Forbidden”, the server or hosting account security rules are blocking this.

ErrorStatus 404 means “File Not Found”, but there is nothing forbidding them accessing the file if it did exist.

(If the requested file did exist, the hackers found a file that, at least in some version of the file, they think had a vulnerability; you wouldn’t see an error. Your site access log would have the file name with an ErrorStatus 200 “OK”, or 304 “Not Modified”.)

ErrorTrigger is my security system letting me know what caused this to be blocked, in this case the use of “wp-content” in the Request String.

Requri is the Request String, in this case beginning with “/wp-content/plugins/work-the-flow-file-upload”. So we guess that some version of the “Work The Flow File Upload” plugin had a vulnerability (because somebody, probably a hacker, was looking for it). We don’t know that the current version of the plugin is flawed, we know that hackers are interested in some version of the plugin.

This plugin looks risky, in the description at https://wordpress.org/plugins/work-the-flow-file-upload/faq/ . However, know that all plugin authors can mess up and allow a hacker to gain access beyond the plugin author’s intentions.

You want to specifically block hacker behavior, and only attempt to guess whether the plugin author is to be trusted while you decide whether to install a plugin.

In this example, simply the attempt to access program files directly in wp-content/ is enough to conclude the request is by a hacker. Only images or music or video should ever be accessible directly, in wp-content/uploads or any sub-folders.

Query String is, in these examples, not used. If you type a URL in, and it has a question mark in it, everything after the question mark is the query string. For the URL http://computerhelp.glerner.com/wp-admin/post.php?post=abcde&action=edit the query string is “post=abcde&action=edit”.

User Agent is used by all software that accesses web pages, letting the server know what capabilities or special formatting to use. Some hackers use web bots with unique names, “bragging” about who they are; these can be blocked by the user agent. In this case, it’s simply Firefox version 34. If there is the word “semalt” or “nutch” or “ImageSucker” in the User Agent, those are known baddies. You can find several lists of user agents, e.g. http://www.useragentstring.com

Cookies aren’t set here. Hmm, if they were actually using WordPress, there would be several cookies set. So, this is another clue they are hackers.

Allow Headers: These are meant to be used to let the server know what language the browser prefers, for example “I want to read the French version of the page if you have one, but if not I’ll take British English or any other version of English”. Similarly, the header is used to indicate if the browser can take compressed output. In this case, no foreign language preferences, and can use gzip or deflate for compression. Nothing to look at here, in this example, for security; this is useful for troubleshooting other types of problems.

Post Variables: Every form you fill out on the Internet uses Post Variables (or rarely, the URL) to submit the data. In this case, the “Action” is “Upload” (the hacker is submitting a file for the server to upload), and the file name is “wp-classes.php”. Well, that looks like a legitimate file name, right? Wrong! This is being uploaded, which is a definite give-away, but if you didn’t catch the upload the hackers are hoping you won’t notice a file with a name that looks legitimate.

How Do I Block Files Uploaded to wp-content/

The easiest way is use a good security plugin such as WordFence (my preference) or iThemes Security (doesn’t include a Web Application Firewall in the free version, and sends useless emails to me, for example “file changes found”). Both will do far more than block uploading executable files and block executing files in wp-content. Definitely use either WordFence or iThemes Security

If you want to modify your own .htaccess file? Don’t, it’s a lot more work! Okay, if you really want to, here’s what I use, including setting a server environment variable that my error page can read:

SetEnvIf Request_URI (?i)^/wp-content/(.*)$  badRequestString=wpcontent
SetEnvIf Request_URI (?i)^/wp-content/themes/(.*)\.(css|js|gif|jpg|jpeg|png|eot|svg|ttf|woff)$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/plugins/(.*)\.(css|js|gif|jpg|jpeg|png|eot|svg|ttf|woff)$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.flv$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.gif$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.jpg$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.jpeg$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.m4v$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.mp3$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.mpeg$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.mpg$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.png$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.pdf$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/uploads/(.*)\.txt$  !badRequestString
SetEnvIf Request_URI (?i)^/wp-content/cache/supercache/(.*)$  !badRequestString
Order Allow,Deny
Allow from all
Deny from env=badRequestString

I make exceptions for style sheets and images and fonts in your theme folders and plugin folders; and for images, pdf files, text files, movies in your WordPress uploads folder (the WordPress Media Library folder). You also should allow cache files (I’m no longer using WP Super Cache, my hosting provider has better).

Want Me to Check Your Security and Do Regular Maintenance?

I do WordPress Ongoing Maintenance and Security for small business sites, making sure your site runs smoothly and is safe from most hackers. I can’t block the CIA (or Russian, Chinese, etc equivalent) from getting in, but I can thwart many hacking attempts at the WordPress and Plugin level. I have your site run quickly, and without errors. I can make sure your pages are showing up well in social media sites, including Facebook, Twitter, LinkedIn, Pinterest.