Detecting Abuse on WordPress Sites

This blog runs on WordPress. It is pretty obvious looking at my basic layout and theme, if not the “Proudly powered by WordPress” stamp at the bottom of this page. WordPress is great, it is easy to setup, easy to manage, write posts for and add plugins. This ease of use attracts a lot of users that tend not to know much of how websites work or web security in general.

Due to this lack of knowledge by some of its users, many WordPress instances are vulnerable to attacks. These attacks may target poorly written plugins, weak passwords, outdated versions of WordPress core or its plugins. Most vulnerabilities for the these targets are widely known by attackers and those attackers write scripts to look for vulnerabilities. Attackers can build up lists of WordPress sites using carefully crafted search engine queries. Site lists combined with automated scrips looking for known vulnerabilities means that attackers can search a large number of sites in a relatively short amount of time.

As a result most WordPress blogs are tested by attackers for vulnerabilities at some point. These tests are usually not very discrete and can be detected in the server logs. I am a curious individual so I look at my logs quite a bit and I see a number of these vulnerability tests. When I first noticed these log entries, I ignored them. When I kept seeing them in the logs I noticed that most of these attacks tests conformed to patterns. This made me wonder if I could detect these attack tests automatically. It turns out for many of them I can.

I accomplished this automation primarily by creating custom 404 and 400 error documents and directing my .htaccess file to use them. In these files I capture the remote IP, request URL and the user agent. In the 404 error handler I examine the request URL for strings that I’ve observed over and over again in my Apache logs; URL requests for files that do not exist in my WordPress instance. These requests are usually for specific files used by plugins that I do not have installed. When I find these request I log the remote IP, time and a short description.

I also examine the user agent strings looking for strings generated by common code libraries like python, pearl, wget, curl and others. These are from scrips written to look for specific files, may of which are testing for vulnerabilities. If I see one of these user agent strings on a non-existent file, I log it. I also added this code to the head of my wp-login.php file, denying access for script user agents and logging any attempts to login. This catches a fair number of scripts trying to bruit force my WordPress login.

Finally in the 400 error document, I again look for specific strings that I’ve found in my logs, logging any matches. All this code results in a list of IPs with descriptions and timestamps. As of writing this post I have not done much with the resulting list so far, but I figured it might be of use to other site admins out there. So for anyone interested in my list of detected malicious IPs it can be viewed at:

The link above provides a CSV file of malicious IPs detected in the last 24 hours. It is also possible to specify the time frame and format. Right now the script supports both csv and json formats and can provide results for a time frame of the last 1 to 336 hours (2 weeks).

Example JSON format for malicious IPs in the last 36 hours:

Example CSV format for malicious IPs in the last 12 hours:

All timestamps are in USA Central time. I plan on updating malicious IP detection and this output script in the future, but plan on using versioning via the v* directory. Feel free to use this list in aggregated block lists for private or commercial use.


Leave a Reply

Your email address will not be published. Required fields are marked *