Module: Msf::Exploit::Remote::WinRM
- Includes:
- Exploit::Remote::NTLM::Client, HttpClient
- Defined in:
- lib/msf/core/exploit/remote/winrm.rb
Instance Attribute Summary
Attributes included from HttpClient
#client, #cookie_jar
Instance Method Summary
collapse
Methods included from HttpClient
#basic_auth, #cleanup, #configure_http_login_scanner, #connect, #connect_ws, #deregister_http_client_options, #disconnect, #download, #full_uri, #handler, #http_fingerprint, #lookup_http_fingerprints, #normalize_uri, #path_from_uri, #peer, #proxies, #reconfig_redirect_opts!, #request_opts_from_url, #request_url, #rhost, #rport, #send_request_cgi, #send_request_cgi!, #send_request_raw, #service_details, #setup, #ssl, #ssl_version, #strip_tags, #target_uri, #validate_fingerprint, #vhost
#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot
optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines
Instance Method Details
#accepts_ntlm_auth ⇒ Object
205
206
207
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 205
def accepts_ntlm_auth
parse_auth_methods(winrm_poke).include? "Negotiate"
end
|
#initialize(info = {}) ⇒ Object
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 17
def initialize(info = {})
super
register_options(
[
Opt::RPORT(5985),
OptString.new('DOMAIN', [ true, 'The domain to use for Windows authentification', 'WORKSTATION']),
OptString.new('URI', [ true, "The URI of the WinRM service", "/wsman" ]),
OptString.new('USERNAME', [ false, 'A specific username to authenticate as' ]),
OptString.new('PASSWORD', [ false, 'A specific password to authenticate with' ]),
], self.class
)
register_autofilter_ports([ 80,443,5985,5986 ])
register_autofilter_services(%W{ winrm })
end
|
#parse_auth_methods(resp) ⇒ Object
37
38
39
40
41
42
43
44
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 37
def parse_auth_methods(resp)
return [] unless resp and resp.code == 401
methods = []
methods << "Negotiate" if resp.['WWW-Authenticate'].include? "Negotiate"
methods << "Kerberos" if resp.['WWW-Authenticate'].include? "Kerberos"
methods << "Basic" if resp.['WWW-Authenticate'].include? "Basic"
return methods
end
|
#parse_wql_response(response) ⇒ Object
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
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 147
def parse_wql_response(response)
return nil if response.nil?
xml = response.body
columns = []
rows =[]
rxml = REXML::Document.new(xml).root
items = rxml.elements["///w:Items"]
items.elements.to_a("///w:XmlFragment").each do |node|
row_data = []
node.elements.to_a.each do |sub_node|
columns << sub_node.name
row_data << sub_node.text
end
rows << row_data
end
columns.uniq!
response_data = Rex::Text::Table.new(
'Header' => "#{datastore['WQL']} (#{rhost})",
'Indent' => 1,
'Columns' => columns
)
rows.each do |row|
response_data << row
end
return response_data
end
|
#send_winrm_request(data, timeout = 20) ⇒ Object
227
228
229
230
231
232
233
234
235
236
237
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 227
def send_winrm_request(data, timeout=20)
opts = {
'uri' => datastore['URI'],
'method' => 'POST',
'data' => data,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD'],
'ctype' => "application/soap+xml;charset=UTF-8"
}
send_request_cgi(opts,timeout)
end
|
#target_url ⇒ Object
209
210
211
212
213
214
215
216
217
218
219
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 209
def target_url
proto = "http"
if rport == 5986 or datastore['SSL']
proto = "https"
end
if datastore['VHOST']
return "#{proto}://#{datastore ['VHOST']}:#{rport}#{@uri.to_s}"
else
return "#{proto}://#{rhost}:#{rport}#{@uri.to_s}"
end
end
|
#winrm_cmd_msg(cmd, shell_id) ⇒ Object
110
111
112
113
114
115
116
117
118
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 110
def winrm_cmd_msg(cmd,shell_id)
action = winrm_uri_action("send_cmd")
options = winrm_option_set([['WINRS_CONSOLEMODE_STDIN', 'TRUE'], ['WINRS_SKIP_CMD_SHELL', 'FALSE']])
selectors = winrm_selector_set([['ShellId', shell_id]])
= action + options + selectors
contents = () + winrm_cmd_body(cmd)
msg = winrm_envelope(contents)
return msg
end
|
#winrm_cmd_recv_msg(shell_id, cmd_id) ⇒ Object
120
121
122
123
124
125
126
127
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 120
def winrm_cmd_recv_msg(shell_id,cmd_id)
action = winrm_uri_action("recv_cmd")
selectors = winrm_selector_set([['ShellId', shell_id]])
= action + selectors
contents = () + winrm_cmd_recv_body(cmd_id)
msg = winrm_envelope(contents)
return msg
end
|
#winrm_delete_shell_msg(shell_id) ⇒ Object
138
139
140
141
142
143
144
145
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 138
def winrm_delete_shell_msg(shell_id)
action = winrm_uri_action("delete_shell")
selectors = winrm_selector_set([['ShellId', shell_id]])
= action + selectors
contents = () + winrm_empty_body
msg = winrm_envelope(contents)
return msg
end
|
#winrm_get_cmd_id(response) ⇒ Object
180
181
182
183
184
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 180
def winrm_get_cmd_id(response)
return nil if response.nil?
xml = response.body
cmd_id = REXML::Document.new(xml).elements["//rsp:CommandId"].text
end
|
#winrm_get_cmd_streams(response) ⇒ Object
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 186
def winrm_get_cmd_streams(response)
return nil if response.nil?
streams = {
'stdout' => '',
'stderr' => '',
}
xml = response.body
rxml = REXML::Document.new(xml).root
rxml.elements.to_a("//rsp:Stream").each do |node|
next if node.text.nil?
streams[node.attributes['Name']] << Rex::Text.decode_base64(node.text)
end
return streams
end
|
#winrm_get_shell_id(response) ⇒ Object
174
175
176
177
178
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 174
def winrm_get_shell_id(response)
return nil if response.nil?
xml = response.body
shell_id = REXML::Document.new(xml).elements["//w:Selector"].text
end
|
#winrm_open_shell_msg ⇒ Object
101
102
103
104
105
106
107
108
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 101
def winrm_open_shell_msg
action = winrm_uri_action("create_shell")
options = winrm_option_set([['WINRS_NOPROFILE', 'FALSE'], ['WINRS_CODEPAGE', '437']])
= action + options
contents = () + winrm_open_shell_body
msg = winrm_envelope(contents)
return msg
end
|
#winrm_poke(timeout = 20) ⇒ Object
33
34
35
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 33
def winrm_poke(timeout = 20)
send_winrm_request(Rex::Text.rand_text_alpha(8), timeout)
end
|
#winrm_run_cmd(cmd, timeout = 20) ⇒ Object
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 46
def winrm_run_cmd(cmd, timeout=20)
resp = send_winrm_request(winrm_open_shell_msg,timeout)
if resp.nil?
print_error "Received no reply from server"
return nil
end
if resp.code == 401
print_error "Login failure! Recheck supplied credentials."
return resp .code
end
unless resp.code == 200
print_error "Got unexpected response: \n #{resp.to_s}"
retval = resp.code || 0
return retval
end
shell_id = winrm_get_shell_id(resp)
resp = send_winrm_request(winrm_cmd_msg(cmd, shell_id),timeout)
cmd_id = winrm_get_cmd_id(resp)
resp = send_winrm_request(winrm_cmd_recv_msg(shell_id,cmd_id),timeout)
streams = winrm_get_cmd_streams(resp)
resp = send_winrm_request(winrm_terminate_cmd_msg(shell_id,cmd_id),timeout)
resp = send_winrm_request(winrm_delete_shell_msg(shell_id))
return streams
end
|
#winrm_run_cmd_hanging(cmd, timeout = 20) ⇒ Object
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 71
def winrm_run_cmd_hanging(cmd, timeout=20)
resp = send_winrm_request(winrm_open_shell_msg,timeout)
if resp.nil?
print_error "Received no reply from server"
return nil
end
if resp.code == 401
print_error "Login failure! Recheck supplied credentials."
return resp .code
end
unless resp.code == 200
print_error "Got unexpected response: \n #{resp.to_s}"
retval = resp.code || 0
return retval
end
shell_id = winrm_get_shell_id(resp)
resp = send_winrm_request(winrm_cmd_msg(cmd, shell_id),timeout)
cmd_id = winrm_get_cmd_id(resp)
resp = send_winrm_request(winrm_cmd_recv_msg(shell_id,cmd_id),timeout)
streams = winrm_get_cmd_streams(resp)
return streams
end
|
#winrm_terminate_cmd_msg(shell_id, cmd_id) ⇒ Object
129
130
131
132
133
134
135
136
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 129
def winrm_terminate_cmd_msg(shell_id,cmd_id)
action = winrm_uri_action("signal_shell")
selectors = winrm_selector_set([['ShellId', shell_id]])
= action + selectors
contents = () + winrm_terminate_cmd_body(cmd_id)
msg = winrm_envelope(contents)
return msg
end
|
#winrm_wql_msg(wql) ⇒ Object
94
95
96
97
98
99
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 94
def winrm_wql_msg(wql)
action = winrm_uri_action("wql")
contents = (action) + winrm_wql_body(wql)
msg = winrm_envelope(contents)
return msg
end
|
#wmi_namespace ⇒ Object
221
222
223
224
225
|
# File 'lib/msf/core/exploit/remote/winrm.rb', line 221
def wmi_namespace
return datastore['NAMESPACE'] if datastore['NAMESPACE']
return @namespace_override if @namespace_override
return "/root/cimv2/"
end
|