{"id":633,"date":"2010-12-23T11:48:41","date_gmt":"2010-12-23T03:48:41","guid":{"rendered":"http:\/\/www.computersolutions.cn\/blog\/?p=633"},"modified":"2010-12-23T11:59:17","modified_gmt":"2010-12-23T03:59:17","slug":"comment-spam-blocking-with-mod_security-debian-and-gotroot-rulesets","status":"publish","type":"post","link":"https:\/\/www.computersolutions.cn\/blog\/2010\/12\/comment-spam-blocking-with-mod_security-debian-and-gotroot-rulesets\/","title":{"rendered":"comment spam blocking with mod_security debian and gotroot rulesets"},"content":{"rendered":"<p>Comment spam is a big load on servers &#8211; recently troubleshooting some intermittent load issues on one of our webservers, I discovered that one page was getting hammered by comment spam abuse &#8211; the page had already generated over 400,000 comments, which was causing the server to be slightly unhappy loadwise.<\/p>\n<p>After clearing out the comment table for that clients site, I looked into solutions.<\/p>\n<p>mod_security was an obvious one, and the <a href=\"http:\/\/www.atomicorp.com\/\">atomic corp rules<\/a> seem to be better than the default mod_security ones (which break most popular apps, sigh).\u00a0 However, although the gotroot rules were good at blocking comment spam, they don&#8217;t block the ip&#8217;s, so persistent spammer bots will still hammer the server.<\/p>\n<p><strong>So, whats a solution?<\/strong><br \/>\nBlocking the ip&#8217;s dynamically for a short period.<br \/>\nAssuming you have a standard setup, the below should be of interest.<\/p>\n<p>I stick my ruleset into \/etc\/modsecurity2, so amend your url&#8217;s accordingly.<\/p>\n<p>My default initialise code is below (pretty much stock except for the end part)<\/p>\n<p>\/etc\/modsecurity2\/modsecurity_crs_10_config.conf<\/p>\n<pre>SecRuleEngine On<\/pre>\n<pre> SecRequestBodyAccess On<\/pre>\n<pre> SecResponseBodyAccess On<\/pre>\n<pre> SecResponseBodyMimeType (null) text\/html text\/plain text\/xml<\/pre>\n<pre> SecResponseBodyLimit 2621440<\/pre>\n<pre> SecServerSignature Apache<\/pre>\n<pre> SecComponentSignature 200911012341<\/pre>\n<pre> SecUploadDir \/var\/asl\/data\/suspicious<\/pre>\n<pre> SecUploadKeepFiles Off<\/pre>\n<pre> SecAuditEngine RelevantOnly<\/pre>\n<pre> SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"<\/pre>\n<pre> SecAuditLogType Concurrent<\/pre>\n<pre> SecAuditLog \/var\/log\/apache2\/modsec_audit.log<\/pre>\n<pre> SecAuditLogParts ABIFHZ<\/pre>\n<pre> SecArgumentSeparator \"&amp;\"<\/pre>\n<pre> SecCookieFormat 0<\/pre>\n<pre> SecRequestBodyInMemoryLimit 131072<\/pre>\n<pre> SecDataDir \/var\/asl\/data\/msa<\/pre>\n<pre> SecTmpDir \/tmp<\/pre>\n<pre> SecAuditLogStorageDir \/var\/asl\/data\/audit<\/pre>\n<pre> SecResponseBodyLimitAction ProcessPartial<\/pre>\n<pre>SecPcreMatchLimit 100000<\/pre>\n<pre>SecPcreMatchLimitRecursion 100000<\/pre>\n<pre>SecDebugLog \/var\/log\/apache2\/modsec_debug.log<\/pre>\n<pre>SecDebugLogLevel 3<\/pre>\n<pre>### Ruleset additions for blocking ########################################<\/pre>\n<pre># Make sure to clear the default action<\/pre>\n<pre>SecDefaultAction phase:1,pass<\/pre>\n<pre># Initialize collection and deprecate by 3 points per day (86400 seconds)<\/pre>\n<pre>SecAction phase:1,initcol:IP=%{REMOTE_ADDR},deprecatevar:IP.spam=3\/86400,nolog<\/pre>\n<pre># If there are already &gt;15 spam points for this IP, then drop<\/pre>\n<pre># the connection and add 1 point (instead of 3, as below).<\/pre>\n<pre>SecRule IP:spam \"@gt 15\" phase:1,setvar:IP.spam=+1,drop,setenv:spam=spam<\/pre>\n<pre># Clear the default action for any mod_security rules later in httpd.conf.<\/pre>\n<pre>SecDefaultAction phase:1,pass<\/pre>\n<pre>### End Ruleset additions for blocking ####################################<\/pre>\n<p><strong>What does it do?\u00a0 Basically we keep score of any ip address that visits the site.<\/strong><br \/>\nEvery day any scores depreciate by 3 points per ip.<br \/>\nIf any ip scores more than 15 points, we block it.<\/p>\n<p>Now, as it stands, its pretty useless, as we don&#8217;t do any scoring.<\/p>\n<p>So, next we&#8217;ll need to add some scoring to some of the rules.<\/p>\n<p>In our case, we were getting seriously hammered by pharmacy spam (mostly out of latvia)<\/p>\n<p>So, I went into the default gotroot ruleset that I installed into \/etc\/modsecurity2<\/p>\n<p>Comment spam is in this file: 30_asl_antispam.conf<\/p>\n<p>I added some scoring there.<br \/>\nIn my case, we saw hundreds of thousands of attempts for levitra and tramadol spam, so I went to the pharmacy scoring, and added this:<\/p>\n<p><code>setvar:IP.spam=+15<\/code> in the SecRule check.<br \/>\nThis means that any positive lookup for that rule will give the ip a 15 point score.<br \/>\nThat will block that attacker ip from the site for 5 days (as  we decrement 3 points per day for a given ip).<\/p>\n<p>The setvar needs to go after the &#8220;capture,&#8230;&#8221; part of the rule.<\/p>\n<p>eg<\/p>\n<p><em>(don&#8217;t copy, paste this, you&#8217;ll need to add &#8220;setvar:IP.spam=+15&#8221; into your existing file)<\/em><br \/>\n<code># Rule 300040:<br \/>\nSecRule ARGS|!ARGS:\/domain\/|!ARGS:description|!ARGS:redirect_to|!ARGS:setting[banemail]|!ARGS:\/username\/|!ARGS:\/user_name\/|!ARGS:\/page_content\/|!ARGS:\/search\/|!ARGS:\/email\/!ARGS:Mensaje|!ARGS:\/product\/|!ARGS:\/domain\/|!ARGS:description$<br \/>\n\"capture,<strong>setvar:IP.spam=+15<\/strong>,id:300040,rev:7,severity:2,msg:'Atomicorp.com - FREE UNSUPPORTED DELAYED FEED - WAF Rules: Spam: Pharmacy',logdata:'%{TX.0}'\"<\/code><\/p>\n<p>I added this to appropriate places, and watched for our first victim^Mspammer in our site logs.<br \/>\nBingo &#8211; here we have a spammer trying to add to a url on one of our sites:<\/p>\n<blockquote><p>[23\/Dec\/2010:11:39:45 +0800] [www.chou.cn\/sid#bcf3f338][rid#b339b670][\/gallery\/papratiti\/img_5993.jpg.php][1] Access denied with code 403 (phase 2). Pattern match &#8220;(?:buy[-_ ]?(cheap)?[-_ ]?(?:adipex|suboxone|pseudovent|topamax|trazodone|prevacid|zyrtec|xenical|toprol|zoloft&#8230;&#8221; at ARGS:comment. [file &#8220;\/etc\/modsecurity2\/30_asl_antispam.conf&#8221;] [line &#8220;194&#8221;] [id &#8220;300061&#8221;] [rev &#8220;10&#8221;] [msg &#8220;Atomicorp.com &#8211; FREE UNSUPPORTED DELAYED FEED &#8211; WAF Rules: Spam: Pharmacy&#8221;] [data &#8220;xanax&#8221;] [severity &#8220;CRITICAL&#8221;]<\/p>\n<p>[23\/Dec\/2010:11:43:16 +0800] [www.chou.cn\/sid#bcf3f338][rid#bfac9d68][\/gallery\/papratiti\/img_5993.jpg.php][1] Access denied with connection close (phase 1). Operator GT matched 15 at IP:spam. [file &#8220;\/etc\/modsecurity2\/modsecurity_crs_10_config.conf&#8221;] [line &#8220;40&#8221;]<\/p><\/blockquote>\n<p>Bam, that ip is blocked (for 5 days).\u00a0 Next time around, as its the first rule to run, it will block immediately without processing other rules.<\/p>\n<p>You can amend the block times by decreasing the increments or scoring as per your requirements.<\/p>\n<p>All in all, this is an easy amendment to make to the gotroot rules, and makes for faster experience for users.<br \/>\nThanks to <a href=\"http:\/\/linux.icydog.net\/apache\/commentspam.php\">http:\/\/linux.icydog.net\/apache\/commentspam.php<\/a> for his implementation, this is pretty much based off that.<\/p>\n<p>Lawrence<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Comment spam is a big load on servers &#8211; recently troubleshooting some intermittent load issues on one of our webservers, I discovered that one page was getting hammered by comment spam abuse &#8211; the page had already generated over 400,000 comments, which was causing the server to be slightly unhappy loadwise. After clearing out the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[48,25,4],"tags":[297,300,301,298,299],"class_list":["post-633","post","type-post","status-publish","format-standard","hentry","category-exploits","category-technical-mumbo-jumbo","category-useful-info","tag-atomicorp","tag-blocking-comment-spam","tag-latvian-spammers","tag-modsecurity","tag-ruleset"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/633","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/comments?post=633"}],"version-history":[{"count":7,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/633\/revisions"}],"predecessor-version":[{"id":635,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/633\/revisions\/635"}],"wp:attachment":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/media?parent=633"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/categories?post=633"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/tags?post=633"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}