Simple Protection for WordPress From Malicious PHP Files

While recently auditing my web server logs for 404 errors, I came across a new pattern of hacker attempts. There were a number of attempts at opening PHP files with a specific name.  A quick search of the internet turned up an article, WordPress Security – Arbitrary File Upload in Gravity Forms by Rodrigo Escobar. The article does a fantastic job of explaining this particular exploit.

To summarize how the attack works, the hacker attempts to exploit a vulnerability identified in the Gravity Forms plugin in order to upload a malicious PHP file to the web site. The file is loaded into the wp-content/uploads path of WordPress. Upon successful upload, they can call the PHP file directly and the Apache server will execute the code. Luckily for me, I don’t have this plugin installed and the attempts on my site were all failed attempts.

The Pattern

As I researched this issue further, it dawned on me that a number of exploits against WordPress work in a similar fashion. The identify a means of exploiting a file upload mechanism within WordPress. These mechanisms are usually designed to place the uploaded file somewhere within the wp-content/uploads directory. The hacker then tries to call the file directly.

As far as I can tell, there should NEVER be a legitimate case where a PHP file needs to be uploaded to this directory and run directly from this directory. The directory was designed to be a place for storing images, videos and documents (Word, PowerPoint, PDFs, etc.). Therefore, if a PHP file does exist in this directory structure, a successful hacker attack is probably already underway.

Solution #1 – Fail2Ban

My first reaction was to setup a new rule in my Fail2Ban system. This software does a great job of monitoring system logs for recurring patterns and then taking automatic action to remedy the problem. In the case of my web applications, it directly manipulates the iptables (software firewall) to block the offender.

I wrote a new rule to identify the access of PHP files in the uploads directory. The regex expression was fairly straightforward:

^<HOST> -.*"(GET|POST).*(?i)\/wp-content\/uploads\/[^"+]*php.*".*"$

I configured the service to block a source IP after just one attempt of this URL pattern. I restarted the Fail2Ban service and did some testing. The filter worked as designed.

The problem with this solution is that if the hacker is successful the first time, they will still be able to perform the hack before the software blocks them for good. It’s unlikely that the hacker will be successful in just one shot, but I don’t want to take that risk.

Solution #2 – Deny Access in Apache Configuration

I decided that I wanted to configure Apache to deny access to any attempt at a PHP file in that directory. A quick search of the internet gave me a couple of good resources. I could make use of the FilesMatch directive in the Apache configuration file to identify a file pattern and block access to that file. I did some testing and I developed the following solution:

        <Directory "/path/to/wordpress/htdocs/wp-content/uploads">
                .............
                <FilesMatch "\.php$">
                        Order allow,deny
                        Deny from all
                </FilesMatch>
        </Directory>

This information goes directly within the VirtualHost configuration for the WordPress web site in the Apache configuration files. After making the configuration change and restarting Apache, I dropped a test PHP file into various directory levels in wp-content/uploads. I tried accessing the PHP file and Apache always gave me a Forbidden access message.

Solution #3 – All of the Above!

The second solution is obviously the better approach. Even if the hacker is successful at uploading a file through an exploited upload mechanism, Apache will make sure that they never actually run the uploaded script. However, security works best in layers. Even though solution #2 is best, keep solution #1 in place too. Even though the hacker can’t succeed in running their script, allow the Fail2Ban software to recognize the attempt and block that hacker from any further exploit attempts on your site. They are obviously up to no good, so keep them from attempting any further harm.

Security Training Should Start in IT

This past week, I attended a seminar titled A Road Map to Security Risk Management through System Source. The presentation was centered around building out a comprehensive plan for understanding your security risks and putting plans and procedures in place to mitigate those risks. There are many factors to consider when building such a plan and this seminar did a great job of getting you thinking about those factors. 

There was one theme in particular that kept coming up in our discussions…training! The attendees of this event all felt very strongly that one of their greatest security vulnerabilities was lack of education and understanding of security matters in their own staff. It is great that we have grown up in a society where we want to be trusting of our fellow citizens. However, there still are those individuals in dark and shady corners of the world who wish to deceive you and we need to take precautions. Giving our staff a better understanding of how these deceptions occur will go a long way to improving security. 

Later in the presentation, we talked about ways we as IT professionals can work to remove security vulnerabilities. For example, developers should plan to do code reviews with their peers. Another example is that network admins can periodically review their network configurations. Then it hit me…do the developers and the network admins talk and work together?

I have had the pleasure of being in environments with large IT departments and seeing what these individuals can do on a daily basis. I have also seen where the individuals in these of environments will very quickly fall into very separate and distinct roles. Unfortunately, this separation of duties often also fosters a separation of communications. We all recognize that our fellow business employees can benefit from additional training, but what about the cross training of information within the IT department.

Let me provide a good example. Recently, I had my network admin hat on and was reviewing my web server logs for any unusual amount of 404 errors. One particular source IP address had an unusually high amount, so I drilled into the detail. When I did, I quickly saw that this source was looking for the FCKEditor at any and all URL patterns imaginable. This was obviously the work of someone up to no good. I did a search on “FCKEditor vulnerability” and a found a document that outlined the exploit. (Exploiting PHP Upload Module of FCKEditor by SecurEyes) It had been identified that a hacker could make use of a null character in a file upload path in order to trick the system into uploading a malicious PHP program. Armed with this knowledge, and knowing that none of our sites made us of the FCKEditor, I took two actions. First, I blocked this particular IP from all access to our servers. Second, I coded our IDS system to recognize this pattern in the future so it could block future attempts in realtime. Another duty of the network admin completed, I moved on to my next project. 

But wait, shouldn’t this information have been shared within our team? My background is largely in programming and as a programmer, I did learn something from this. Maybe this information should be shared with other programmers on our team so that they can continue to improve their own code. What about our support staff and sales team? When they talk to end users about security, the more they understand the vulnerabilities, the easier it is to talk about the overall subject. The IT manager? Are you looking to buy that latest and greatest IDS appliance for your network? Your boss should understand why they need to approve the costs for such appliances. This also helps them communicate better with the senior managers when discussing budgets and corporate strategies.

As IT professionals, we know that the learning process never ends. But let’s not forget to support each other in our learning too. The more we share this knowledge among ourselves, the better prepared we all are for any security situation. 

Encrypting WordPress Administration

Since I am just setting up my WordPress blog, I thought that my first post should be about securing administration of the site. I wanted to have my site setup so that if you go to the admin login screen, you will be forced to do so over an encrypted connection on HTTPS. After doing a little bit of research, I found that there is a setting within WordPress that takes care of this for you.

To start the process, setup your site to be accessible by both HTTP and HTTPS. (This might be a good article for a future date!) After you are able to access your site with each of these protocols, then add the following line of text to your wp-config.php file:

define(‘FORCE_SSL_ADMIN’, true);

Now try to access your WordPress administration login and you will notice that it automatically redirects you to the HTTPS port.