Because comments can be left on my various blog posts, I suffer the same problem of comment spam as many other websites. Armies of bots scour the Internet searching for pages which they can automatically post to. They post URLs linking back to their own websites in an attempt to improve their rankings with the various search engines.
I moderate and manually approve all comments before they appear on my blog, so spam never actually manages to get through. However, it is very annoying having to manually check and delete these messages. I’ve come up with a solution to automatically detect these bots and block them using ModSecurity.
My “Add comment” forms have several text fields. They’re named, “name,” “email,” “website,” and “body.” I added an extra text field named “confirm_email” but I hid it inside an invisible container, similar to this:
<div style="display:none;"> <input type="text" name="confirm_email"> </div>
After I did this, the bots started filling in the “confirm_email” field with the same data they were putting in the “email” field. Real people don’t see this field because it is hidden, so it remains empty. Some text-mode browsers don’t support CSS so it might be worth leaving a comment next to the text field, inside the hidden container, specifying that it should be left empty.
Now, any post where “confirm_email” is not empty, can be blocked. Rather than doing this in the application its self, I decided to use the web application firewall which I already had installed inside Apache, named ModSecurity. Here is the relevant Apache config inside my VirtualHost:
SecRuleEngine On SecRequestBodyAccess On SecRule REQUEST_METHOD "@streq POST" "phase:2,deny,status:403,chain" SecRule REQUEST_URI "^/+[^/]+$" "chain" SecRule ARGS:action "@streq add_comment" "chain" SecRule ARGS:confirm_email !^$
The first two lines turn on ModSecurity and enable filtering on HTTP request bodies. The next four lines are chained together to create a single rule. If the request method is “POST,” the URI matches a particular regular expression, and the request has an “action=add_comment” parameter and non-empty “confirm_email” parameter, then the request is intercepted and a 403 Forbidden page is returned.
Such is the awesome power of ModSecurity. I’m not the first person to think of using a hidden input field to detect and block comment spam bots, however I’ve not seen it done with ModSecurity before.