Wednesday, August 17, 2011

Http Parameter Contamination (more)

To continue investigating the Http Parameter Contamination (HPC) attack, I’ve done some primitive fuzzing in the environments which had not been covered in the original research of Ivan Markovic. It must be mentioned, that I have not found out anything new. On the other hand, an interesting feature of the Python interpreter was revealed; I also got a payload exploit for conducting a denial-of-service attack against the Tomcat server:) But I won’t disclose anything else about the latter so far.

The results are presented in the figure below.

* the "\0" character means that null byte is correctly processed by the application.

The most interesting features are marked in dark red. Features which are slightly less interesting but worthy of attention are highlighted in pale red. Let’s examine these results in details.

The specifics of how incoming data is processed by an ASP web-application are the most valuable feature for an attacker. The thing is that an ASP application simply deletes the "%" character in the parameter name or parameter value if the character does not make a legal character when decoding a URL. This feature allows easy bypassing of different security filters and Web Application Firewall which are applied before the application processes the incoming data. In his survey, Ivan Markovic brings the example of how the Mod_Security rules are bypassed when exploiting the Path traversal vulnerability:
MSSQL DBMS and the SQL Injection vulnerabilities which have been revealed in the application are more applicable to the IIS platform. By using this method, this vulnerability can be exploited in the same way in bypass of the relevant Mod_Security rules:

?id=1;selec%t+convert(int,(selec%t+table%_name+from(selec%t+row_number()+over+(order+by+table%_name)+as+rownu%m,table%_name+from+information_schema.tables)+as +t+where+t.rownu%m=1))--

It must be noted here, that this refers to bypassing the base rules of Mod_Security. If extended rules (optional or experimental) are used, this trick will not work.

Other specific features of data processing which are as useful as the feature described above refer to the PHP interpreter. These are the implicit conversion of types (?param[]=123 -> param=Array) which is well-known to anyone and also the control over the  $_SERVER["argv"] (?1+2) array when the "on" value is set in the "register_argc_argv" configuration. The attacker may use the first specific feature of PHP to bypass various restrictions (for example, when the variables are compared implicitly) as well as to force an error message to be displayed (for example, accessing the root directory of a web server). Another specific feature of PHP allows running a script form the web server and deliver the parameters which the script receives from the command line.

The substitution of the “+", ".", "[" characters and "space" for the underscore character ("_") is a slightly less interesting feature of PHP. Why this feature brings less damage? The thing is that PHP behaves in this way only when the web server receives parameter names rather than the values of these parameters. This fact significantly reduces the chance that this feature will be used in practice.

And the last thing I want to draw your attention to is the Python interpreter. Fuzz testing revealed that when Python detects characters of the %80-%FF range, it returns an error (disclosure, etc.)):

I used these scripts for testing.


$G = &$_GET;
foreach ($G as $k=>$v)
print $k."=".$v;

for each var in Request.QueryString
   Response.Write ( var & "=" & Request.QueryString ( var ) )

java.util.Enumeration names = request.getParameterNames();
String keyx = names.nextElement().toString();
out.println(keyx + "=" + request.getParameter(keyx)); }

use CGI;
my $cgi = new CGI;
my @params = $cgi->param();
print <
HTTP/1.0 200 OK
Content-Type: text/html

foreach my $parameter (sort @params) {
print $parameter."=".$cgi->param($parameter);

import cgi, os

print ('Status: 200 OK')
print ('Content-type: text/html; charset=utf-8;')

query = os.environ.get('QUERY_STRING')

pairs = cgi.parse_qs( query )

for key, value in pairs.items():
    print (key,value)