Fail2ban + WordPress + Nginx

I’ve been using the Limit Login Attempts plugin for WordPress for quite a while. It basically logs failed login attempts and automatically blocks multiple attempts from a single IP address. A few days ago I’ve switched to fail2ban instead, which is pretty new to me.

Fail2ban with WordPress and Nginx

Fail2ban is a fairly simple yet very flexible framework that monitors log files for certain patterns, and runs preconfigured actions upon certain events.

Out of the box fail2ban comes with many so called filters, which are sets of matching rules, for example SSH auth failure, vsftpd login failure and more. As well as predefined actions, like block the IP address via iptables, send an e-mail with the IP WHOIS info, etc.

I haven’t had too much time to play around with the configs, but I did manage to get it to work with my WordPress install on nginx, and here’s how.

Continue reading

Don’t Hide the Fact That You’re Using WordPress

There are quite a few blog posts, plugins and hacks suggesting to hide the WordPress version number, or hide the overall fact that you’re using WordPress. Don’t do it — it’s pretty useless.

There are hundreds if not thousands of ways to not only find out the fact that you’re using WordPress, but also find out the exact version number, regardless of any plugins or hacks changing or hiding the “generator” meta tag, the readme file and so on. A great post by my brother Gennady illustrates that.


Most of these “hide my WP” solutions tend to market themselves from a security standpoint, especially with the recent botnet attack on WordPress sites. The truth is that these attacks don’t really care which version of WordPress you’re running. In fact, they don’t even care whether you’re running WordPress at all! How? Well that’s easy, they just take your domain and blindly fire POST requests to a file called wp-login.php, even if you’re running a non-CMS pure HTML website.

The same applies to known theme and plugin vulnerabilities. Go ahead and check your web server’s access logs, there’s a pretty good chance you’ll find requests to timthumb.php even though none of your themes or plugins use the TimThumb library.

So from a security perspective, the secret sauce is to use a strong password, as well as keep your themes, plugins and especially WordPress core up to date. Plugins such as Google Authenticator and Limit Login Attempts can give you that little extra protection.

The Ferrari Analogy

Sometimes people try hide the fact that they’re running WordPress because they’re afraid other humans will spot that and think they’re “unprofessional” or cheap. Well WordPress is the most professional content management system known to human kind, trusted by some of the largest companies worldwide and although free and open source, certainly not cheap.

When you buy yourself a new Ferrari, do you remove the Ferrari logos before showing it to your friends? No. Although if you did, it would still be obvious.

To wrap that up — don’t hide the fact that you’re using WordPress. Use a strong password, keep it updated and drive it with pride. If you bought a premium “hide my WordPress” plugin, you should ask for a refund and buy something useful instead.

Github’s Asking for my Password

“Why is Github asking me to input my username and password when I try to push changes to a repository I own?” I asked this myself a couple of times before I figured out I had cloned it the wrong way:

git clone .

As opposed to:

git clone .

Where the former will use the HTTP protocol, and thus require basic authentication (username and password), and the latter will use the SSH protocol, and will try to use my SSH key instead, for password-less authentication. The former will work, but you’ll have to keep entering your username and password every time. The latter is more secure.

Simple, but tricky. No, I don’t use a GUI for version control, and neither should you, trust me :)

Thoughts on “Too Much Escaping” in WordPress

While sanitizing and escaping everything is very important when dealing with websites, I think there are times when we need to back off a little bit, and trust the functions that have been given to us by WordPress.

<a href="<?php echo esc_url( get_permalink( get_the_ID() ) ); ?>" title="<?php echo esc_attr( sprintf( __( 'Permanent Link to %s', 'domain' ), the_title_attribute( array( 'echo' => false ) ) ) ); ?>" >

I call that paranoia (and I see it in a lot of themes.) Dirty, difficult to read and understand, and even more difficult to spot an error. The permalink and the title attribute are never going to break out of the attributes syntax and escaping them a billion times doesn’t really help. Here’s a cleaner version for comparison:

<a href="<?php the_permalink(); ?>" title="<?php the_title_attribute( array( 'before' => __( 'Permanent link to ', 'domain' ) ) ); ?>" >

Quite straightforward and easy to understand. You don’t even need to worry about escaping the “before” text, because the_title_attribute will escape it for you. One might argue that explicit escaping (right at the output) is more secure than implicit escaping, but since functions prefixed with the_ are meant for output, I tend to trust their output. You just need to know where each one should go.

With that said, if you have a super hi-jacked WordPress installation with a malicious plugin overwriting the output of the functions mentioned above, there’s really not much you can do. Even if you triple espace with get_permalink, a plugin might just filter in on post_link and output whatever it needs to output by-passing all escaping.


Dear WordPress Theme Developers, Stop Using TimThumb

Just a reminder, since this weekend I had to help out with yet another TimThumb-powered WordPress theme, broken by a “security patch” at the web hosting provider. This time it was Acquisto by Press75. The problems of Acquisto are not limited to thumbnails.

Protected Meta in WordPress

I was doing a few tweaks to the Twitter Embed plugin earlier today and found out that authors that access to the custom fields interface could exploit them to print unfiltered HTML. This happened because I cached the HTML retrieved from the Twitter API in an unprotected meta field to the post.

The easiest workaround was to add an underscore prefix to the meta key, so my_meta_key for example, would become _my_meta_key. For a second though, I thought that somebody might type in the underscore in the custom fields interface too, so I spent a few minutes reading the admin ajax source code.

It turns out that there is a call to a function called is_protected_meta defined in meta.php, which does the check for the preceding underscore, so the custom fields interface will not allow working with protected meta fields no matter on what user level, which is good! It still allows themes and plugins to use get_post_meta and update_post_meta.

So the lesson learned today — if you’re storing sensitive data in your post meta fields, don’t forget to protect them from eyes by prefixing your meta keys with underscores.

Wired News & Twitter

I’ve read an entry in the livejournal webdev community today – a link to a great blog post on Wired News about “the battle of the browsers”. Following the link I got onto the Wierd News Blogs website, and with a timeout of about 5 seconds I received a javascript popup message asking for my Twitter username and password. This looks like scam. Why the heck would a PR9 news resource do this?

Wired News Twitter