Wordfence is a security plugin for WordPress. You can download Wordfence for free from the WordPress repository. If you prefer, you can use the plugin auto-installer from your installation’s wp-admin.
This is a follow-up to my earlier post, a review of Better WP Security.
Installing the Wordfence security plugin
For this review, I tested Wordfence version 3.8.8 on WordPress version 3.7.1 running in debug mode on my test environment, with display_errors set to “on” in my php.ini. I checked the plugin’s front-end display using the ever-popular default theme, TwentyTwelve 1.3.
The .zip file for Wordfence 3.8.8 is 1.53MB, and takes up 3.53MB of disk space on my system when extracted.
Plugin reputation
Wordfence is a well-respected security plugin for WordPress. I have seen the little WordFence icon in the sidebar of tutorial screenshots posted by some of the leading minds working in WordPress today. The Wordfence security plugin has been downloaded well over a million times (1.04 million and counting) and enjoys a stellar 4.9 out of 5 star ranking.
I do always read the 1 star reviews, to be on the lookout for potential problems. One user states that the plugin does not provide adequate security; a few complain about false positives; and the rest of the negative reviews state that the plugin slowed their site or increases the database size (which would slow the site on oversold commercial hosts like some big names I won’t mention here).
Still, the plugin has been given a 5-star rating by 93% of reviewers. Based on more than 1.04 million downloads, that’s a very positive rating. It’s worth checking out.
First impressions
When I activate Wordfence, the first thing I see is a nag to sign up for the e-mail list. No, thanks…
I also note that Wordfence does not immediately cause a conflict with my caching plugin. This is a vote in its favor, and an improvement over the last security plugin I tested.
Now I visit the Wordfence administration screen. Actually, clicking the Wordfence icon in the left-hand sidebar just opens the “scan” sub-menu. There is no one-click “fix all your problems” button. So before looking at all the options, let’s first examine what changes Wordfence made to the system when we activated it.
Behind the scenes
No additional setup is required in order to get Wordfence up & running.
Well, Wordfence certainly has a more obvious database footprint than the last plugin I tested. It creates no less than 19 new tables in the database. (This review would get pretty boring if I listed them all.) However, I remember that the previous plugin had such long data entries in the columns that I couldn’t even read them from the console. So appearances may be deceiving in this respect.
Wordfence also creates three new records in the wp_options table. These track plugin activation errors; the activated state of the plugin; and the current version of the plugin.
There aren’t obvious changes to the filesystem when the plugin is activated. The “tmp” folder within the plugin folder says it was modified; but the modification is not immediately apparent, so apparently a temporary file was stored there and deleted, as the folder name implies.
The result
Wordfence logs traffic in real time. The logs are viewable from the “live traffic” option in the sidebar. This can be convenient if you are obsessively watching your traffic in real time. I have days like that, especially after receiving a slew of malicious hits. But on most days, we all have better things to do.
The point being, in order to log traffic, Wordfence adds a JavaScript snippet to the output of wp_head().
The snippet requires all visitors to make an AJAX call before their browser can even load the page. There’s no obvious way to tell Wordfence that you’d prefer to have all JavaScript output in your website’s footer. From an optimization standpoint, that’s an unfortunate drawback.
There’s also the caching plugin issue. Wordfence appears to generate a unique ID for each page load, and attaches it to the AJAX call in the head as a query string. However, if you’re using a caching plugin, this ID is cached along with the rest of the page, so traffic from multiple visitors could be associated with a single visitor in the logs.
Let’s check out the Wordfence settings and admin menu.
Scan
The first option is the “Scan” menu. This feature is undoubtedly the coolest thing about Wordfence, and has required the plugin developer to invest in some non-trivial network resources of their own in order to support it.
The free version scans all the files in your WordPress installation, and compares them against the known file version from the repository (if you select the appropriate box in the “options” menu). If there is a mismatch, Wordfence displays an error message (or e-mails it to you, depending on your settings). Usually a mismatch is caused by outdated versions of your theme, plugin, or core files, so these notifications are your notice that it’s time for an update. However, the major concern is that if your system has been compromised, an attacker could have planted a back door in one of these files. By comparing the files on your server against the version in the repository, Wordfence can detect changes to your system, and notify you of potentially critical security issues.
There is also the option to scan all the files in your site for known malware signatures; but that requires upgrading to the paid version. Which may be well worth it.
Live Traffic
Wordfence’s traffic log is a neat feature. You can see a listing of recent visits by bots and humans. It lists IP address, User-Agent string, and the associated country flag of the visitor’s location, if known. However, as mentioned above, this log may not be reliable if you are running a caching plugin such as W3 Total Cache or WP Super Cache.
Wordfence logs human traffic via AJAX calls. This will fail for the less than 2% of human visitors who have JavaScript disabled (usually from privacy concerns, but sometimes due to accessibility issues). Note that these AJAX calls are not made to a file within the Wordfence plugin folder; they are sent straight to /wp-admin/admin-ajax.php. This means that if your site’s admin folder is protected by a custom .htaccess deny rule, then the traffic logging will always fail.
Wordfence also tracks bots. Generally, you can tell bots from humans because they don’t execute JavaScript or load images. Most of the better bots will have a user-agent string that contains the word “bot,” but it’s the bad bots you have to worry about, and you never know what they might claim to be.
There’s even a feature to ban visitors by IP address. This allows you to block known screen scrapers, hackers, or that same so-called SEO spammer guy from India who refuses to give up and keeps sending messages from your contact form with a different name every week. I have a strong suspicion that the “Ban” feature is not effective if your site is using a caching plugin. I haven’t managed to verify my suspicion at this time. This is an advanced topic, and might be worthy of its own follow-up post.
Blocked IPs
The next menu option is “Blocked IPs.” Like the last plugin I tested, this one won’t let you block yourself. That’s a good thing from a usability perspective: you won’t accidentally block yourself, which is surprisingly easy to do, since you as the site owner are likely to demonstrate an unusual browsing pattern. Unfortunately that makes this system more difficult for me to test.
I attempt to add my IP address to the Wordfence ban table in the database manually; but it turns out I need the long IP, the standard IPV4 syntax doesn’t work. This exercise has gotten silly, but why should that stop me now?
First I re-installed the plugin with a clean cache. Then I visited the home page in Chrome. A minute later I visited the same page in IE10, and a moment after that, I viewed it a third time in IE7. I go to the Live Site Activity tab, and it only shows me the first visit, from Chrome. It does not register my return visits to the same page in the other browsers.
I visit a new page in Chrome, and Wordfence’s logger generates a new visitor ID for the AJAX call. I refresh the homepage in IE, and it still has the old, cached ID. I visit the second page in IE, and it now shows the second ID that I got in Chrome. Back in the Wordfence Live Site Activity, I’m still only seeing the first page view for each page: the hit that created the cache. This should prove my point.
But my point won’t be completely proven until I attempt to ban myself.
Fortunately, I’ve written a simple script for getting the long IP of an IPV4, it’s an early version of my CIDR Test script.
Using my long IP, a correct timestamp, and a Boolean “true” for the “permanent” column, I am finally able to ban myself. At least, the ban tab says I’m banned. But I can load a cached page without any trouble.
I briefly, mistakenly think that my case is proven. A caching plugin will eliminate the benefit of any IP-based banning by a security plugin.
But… after much quackery and local network hackery, finally I see a note at the very bottom of the “Options” menu, under “Other Options”, with the text greyed out so you would hardly notice it, “Wordfence automatically whitelists private networks because these are not routable on the public Internet.” So banning my own IP address in the test environment has no effect, because my local network is whitelisted by default.
Ai yi yi. Some other time then.
More features
Back to the review, Wordfence has a lot more features.
Cellphone sign-in. Wordfence offers two-factor authentication for wp-admin logins. This effectively eliminates the threat of brute force attacks; because even if they guess your password, they won’t have your cell phone. However, this feature is only available for paid subscribers. And rightfully so, this is another feature that required the plugin author to develop their own nontrivial network capabilities.
Country blocking is also only available with the paid upgrade. However, I have some doubts about the ban functionality.
Scan Scheduling is only available with the upgrade. By default, the free version scans your site daily, which is entirely sufficient for the average website owner.
Whois Lookup searches the WHOIS database to find out who owns the domain or network of an attacker or suspicious visitor.
Advanced blocking allows you to ban entire IP address ranges.
The Options menu presents essential plugin configuration options. It’s easy to overlook; but many essential security features are here, checked by default and not requiring much time or attention from the user. This is a user-friendly approach. Some of the defaults include:
- Send or present an alert when problems are found
- Log traffic
- Regularly scan core files for changes
- Enable firewall (but you have to remember to configure the firewall rules)
- Enforce strong passwords
- disable WordPress’s overly-helpful login error messages
- lock out visitor after multiple login failures (but the default setting is far too generous). This will not stop a brute force attack but
- Hide WordPress version, scan comments, limit the plugin’s own memory usage
On the “Advanced Options” settings of the “Options” menu, you can configure the option to engage in “throttling” of overzealous bots. Have you ever looked at your log files, and you can see when your site got hit by a screen scraper that just went through and visited every single URL on your domain within just a few minutes by hammering on your site with no consideration for the fact that they’re consuming all your server resources and sometimes causing 508 “Service Unavailable” errors? Well, I have, and it’s not a good feeling. So it’s great to have an option like this that will shut down those types of excessive requests. Real humans will not be affected, because humans operate at human speed, not bot speed.
Public-facing code changes
The “log humans” JavaScript snippet is output in the wp-head. As I mentioned above, there is no option to move the JavaScript to the footer for performance optimization. This will not noticeably affect most users. It could have a slightly negative impact on page load times for users on slow networks, old computers, or mobile devices; but we’re still talking about fractions of a second in most cases. The fact that the logging code is there does sort of publicly announce that your site is running the Wordfence plugin. That’s fine, unless a vulnerability is ever discovered in this plugin. However, the plugin authors seem dedicated to their work, so I’d imagine any vulnerability would likely be patched quickly. Also, if you really want it gone, you can just go to the Options menu and uncheck the appropriate box.
Uninstalling
The final test of a good plugin is to see how gracious it is when you say “good-bye.” Let’s see how Wordfence compares.
Disabling the plugin does not make any apparent changes to the database.
Oh, bad news. Deleting the plugin does not make any apparent changes to the database. The plugin files are gone, but its records are still there in the database. The same is true for the plugin’s entries in the options table. What am I supposed to do, delete them manually? There doesn’t seem to be much choice, if I’m going to start the next review with a clean slate.
Now I see the problem. If you want to delete the plugin’s data from the database, you have to go to the very, very bottom of the Options menu, under Other options, and select the box that says, “Delete Wordfence tables and data on deactivation.”
That’s a bit of a “gotcha,” but it’s reasonable, and certainly an improvement over plugins that don’t offer database cleanup at all.
Try that again… Here’s what I get:
If the user has checked the box, “Delete Wordfence tables and data on deactivation” in the options menu prior to uninstalling the plugin, Wordfence will clean up after itself and delete all database tables. It also deletes most of the installation data from the wp_options table. However, I found that there was one Wordfence entry in wp_options that was not deleted upon uninstallation.
This is not a significant usability issue; but I’m trying to be thorough in my review here.
Assessment
WordFence’s core strengths are real-time visitor tracking and file scanning. The bot throttling option is an excellent feature. Two-factor authentication via cell-phone sign in is available as a paid upgrade, and may be well worthwhile for some users.
Wordfence also provides the essential security features that you would expect from a security plugin. It enforces cryptographically strong password rules, and hides the login error message that would otherwise tell an attacker whether or not they had guessed the correct username. It locks out an attacker’s IP address after multiple failed login attempts. As I keep saying, banning by IP is no longer a sufficient protection against distributed botnets; but why make it easy for them, right?
Some of the plugin’s features (firewall/throttling ban) may be less effective if you are using a caching plugin; but that was also true of the last security plugin I reviewed.
All told, Wordfence is an impressive security plugin.
How does Wordfence compare to other WordPress security plugins? Stay tuned and let’s find out. First, I’m going to review some more plugins individually. Then I will conclude the series with a final evaluation, and I will pick a winner.
Next up: BulletProof Security. Until then, have a secure day.
Update: Cron Conflict
After running Wordfence on one of my live sites for several weeks, I’m seeing an apparent conflict caused by the plugin. The error log has filled up alarmingly fast with a long, long list of errors like this:
WordPress database error MySQL server has gone away for query SELECT option_value FROM wp_options WHERE option_name = '_transient_doing_cron' LIMIT 1 made by _get_cron_lock
This error is repeated daily, sometimes as often as four times a day. And when I go through my server logs, the error always occurs when WordPress’s own internal cron job emulator sends a POST request to
/wp-cron.php?doing_wp_cong={someLongStringOfRandomNumbers}
at the same time that Wordfence makes a POST call to
/wp-admin/admin-ajax.php?action=wordfence_testAjax
immediately followed by a call to
/wp-admin/admin-ajax.php?action=wordfence_doScan&isFork=0&cronKey={someDifferentHash}
In other words, if a Wordfence scan and a WordPress cron start at the same time, the database connection fails and the cron job throws an error, which Apache records in the error log file.
Unfortunately, on a site with only a modest amount of traffic, these two tasks are highly likely to occur at the same time, resulting in collisions several times a day. In brief, Wordfence is filling up my log files with errors.
I will be taking this into consideration in my eventual comparative evaluation.