diff --git a/lib/msf/core/exploit/winrm.rb b/lib/msf/core/exploit/winrm.rb
index 9037e99e5a..03fc2a6f3a 100644
--- a/lib/msf/core/exploit/winrm.rb
+++ b/lib/msf/core/exploit/winrm.rb
@@ -25,7 +25,7 @@ module Msf
OptString.new('VHOST', [ false, "HTTP server virtual host" ]),
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL3', 'TLS1']]),
- OptString.new('DOMAIN', [ true, 'The domain to use for windows authentification', 'WORKSTATION']),
+ 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' ]),
@@ -35,10 +35,11 @@ module Msf
register_autofilter_ports([ 80,443,5985,5986 ])
register_autofilter_services(%W{ winrm })
end
+
def winrm_poke(timeout = 20)
opts = {
'uri' => datastore['URI'],
- 'data' => 'test'
+ 'data' => Rex::Text.rand_text_alpha(8)
}
c = connect(opts)
to = opts[:timeout] || timeout
@@ -51,14 +52,16 @@ module Msf
}))
return resp
end
+
def parse_auth_methods(resp)
- return [] unless resp.code == 401
+ return [] unless resp and resp.code == 401
methods = []
methods << "Negotiate" if resp.headers['WWW-Authenticate'].include? "Negotiate"
methods << "Kerberos" if resp.headers['WWW-Authenticate'].include? "Kerberos"
methods << "Basic" if resp.headers['WWW-Authenticate'].include? "Basic"
return methods
end
+
def winrm_run_cmd(cmd, timeout=20)
resp,c = send_request_ntlm(winrm_open_shell_msg,timeout)
if resp.code == 401
@@ -67,7 +70,8 @@ module Msf
end
unless resp.code == 200
print_error "Got unexpected response: \n #{resp.to_s}"
- return resp.code
+ retval == resp.code || 0
+ return retval
end
shell_id = winrm_get_shell_id(resp)
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id),timeout)
@@ -85,6 +89,7 @@ module Msf
msg = winrm_envelope(contents)
return msg
end
+
def winrm_open_shell_msg
action = winrm_uri_action("create_shell")
options = winrm_option_set([['WINRS_NOPROFILE', 'FALSE'], ['WINRS_CODEPAGE', '437']])
@@ -93,6 +98,7 @@ module Msf
msg = winrm_envelope(contents)
return msg
end
+
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']])
@@ -102,6 +108,7 @@ module Msf
msg = winrm_envelope(contents)
return msg
end
+
def winrm_cmd_recv_msg(shell_id,cmd_id)
action = winrm_uri_action("recv_cmd")
selectors = winrm_selector_set([['ShellId', shell_id]])
@@ -110,6 +117,7 @@ module Msf
msg = winrm_envelope(contents)
return msg
end
+
def winrm_terminate_cmd_msg(shell_id,cmd_id)
action = winrm_uri_action("signal_shell")
selectors = winrm_selector_set([['ShellId', shell_id]])
@@ -118,6 +126,7 @@ module Msf
msg = winrm_envelope(contents)
return msg
end
+
def winrm_delete_shell_msg(shell_id)
action = winrm_uri_action("delete_shell")
selectors = winrm_selector_set([['ShellId', shell_id]])
@@ -152,14 +161,17 @@ module Msf
end
return response_data
end
+
def winrm_get_shell_id(response)
xml = response.body
shell_id = REXML::Document.new(xml).elements["//w:Selector"].text
end
+
def winrm_get_cmd_id(response)
xml = response.body
cmd_id = REXML::Document.new(xml).elements["//rsp:CommandId"].text
end
+
def winrm_get_cmd_streams(response)
streams = {
'stdout' => '',
@@ -169,127 +181,13 @@ module Msf
rxml = REXML::Document.new(xml).root
rxml.elements.to_a("//rsp:Stream").each do |node|
next if node.text.nil?
- streams[node.attributes['Name']] << Base64.decode64(node.text)
+ streams[node.attributes['Name']] << Rex::Text.base64_decode(node.text)
end
return streams
end
- def winrm_option_set(options)
- xml = ""
- options.each do |option_pair|
- xml << winrm_option(*option_pair)
- end
- xml << ""
- return xml
- end
- def winrm_option(name,value)
- %Q{#{value}}
- end
- def winrm_selector_set(selectors)
- xml = ""
- selectors.each do |selector_pair|
- xml << winrm_selector(*selector_pair)
- end
- xml << ""
- return xml
- end
- def winrm_selector(name,value)
- %Q{#{value}}
- end
- def winrm_wql_body(wql)
- %Q{
-
-
-
- 32000
- #{wql}
-
-
- }
- end
- def winrm_open_shell_body
- %q{
-
- stdin
- stdout stderr
-
- }
- end
- def winrm_cmd_body(cmd)
- %Q{
-
- "#{cmd}"
-
- }
- end
- def winrm_cmd_recv_body(cmd_id)
- %Q{
-
- stdout stderr
-
- }
- end
- def winrm_terminate_cmd_body(cmd_id)
- %Q{
-
- http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate
-
- }
- end
- def winrm_empty_body
- %q{}
- end
- def winrm_envelope(data)
- %Q{
-
- #{data}
- }
- end
- def winrm_header(data)
- %Q{
-
- #{target_url}
-
- http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
-
- 153600
- uuid:#{generate_uuid}
-
-
- PT60S
- #{data}
-
- }
- end
- def winrm_uri_action(type)
- case type
- when "wql"
- return %q{http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*
- http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate}
- when "create_shell"
- return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
- http://schemas.xmlsoap.org/ws/2004/09/transfer/Create}
- when "send_cmd"
- return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
- http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command}
- when "recv_cmd"
- return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
- http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive}
- when "signal_shell"
- return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
- http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal}
- when "delete_shell"
- return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
- http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete}
- end
- end
+
def generate_uuid
- bytes = ::SecureRandom.random_bytes(16)
- ::Rex::Proto::DCERPC::UUID.uuid_unpack(bytes)
+ ::Rex::Proto::DCERPC::UUID.uuid_unpack(Rex::Text.rand_text(16))
end
def send_request_ntlm(data, timeout = 20)
@@ -379,9 +277,11 @@ module Msf
rescue ::Errno::EPIPE, ::Timeout::Error
end
end
+
def accepts_ntlm_auth
parse_auth_methods(winrm_poke).include? "Negotiate"
end
+
def target_url
proto = "http"
if rport == 5986 or datastore['SSL']
@@ -393,5 +293,135 @@ module Msf
return "#{proto}://#{rhost}:#{rport}#{@uri.to_s}"
end
end
+
+ private
+
+ def winrm_option_set(options)
+ xml = ""
+ options.each do |option_pair|
+ xml << winrm_option(*option_pair)
+ end
+ xml << ""
+ return xml
+ end
+
+ def winrm_option(name,value)
+ %Q{#{value}}
+ end
+
+ def winrm_selector_set(selectors)
+ xml = ""
+ selectors.each do |selector_pair|
+ xml << winrm_selector(*selector_pair)
+ end
+ xml << ""
+ return xml
+ end
+
+ def winrm_selector(name,value)
+ %Q{#{value}}
+ end
+
+ def winrm_wql_body(wql)
+ %Q{
+
+
+
+ 32000
+ #{wql}
+
+
+ }
+ end
+
+ def winrm_open_shell_body
+ %q{
+
+ stdin
+ stdout stderr
+
+ }
+ end
+
+ def winrm_cmd_body(cmd)
+ %Q{
+
+ "#{cmd}"
+
+ }
+ end
+
+ def winrm_cmd_recv_body(cmd_id)
+ %Q{
+
+ stdout stderr
+
+ }
+ end
+
+ def winrm_terminate_cmd_body(cmd_id)
+ %Q{
+
+ http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate
+
+ }
+ end
+
+ def winrm_empty_body
+ %q{}
+ end
+
+ def winrm_envelope(data)
+ %Q{
+
+ #{data}
+ }
+ end
+
+ def winrm_header(data)
+ %Q{
+
+ #{target_url}
+
+ http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
+
+ 153600
+ uuid:#{generate_uuid}
+
+
+ PT60S
+ #{data}
+
+ }
+ end
+
+ def winrm_uri_action(type)
+ case type
+ when "wql"
+ return %q{http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*
+ http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate}
+ when "create_shell"
+ return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
+ http://schemas.xmlsoap.org/ws/2004/09/transfer/Create}
+ when "send_cmd"
+ return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
+ http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command}
+ when "recv_cmd"
+ return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
+ http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive}
+ when "signal_shell"
+ return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
+ http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal}
+ when "delete_shell"
+ return %q{http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd
+ http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete}
+ end
+ end
+
end
end
diff --git a/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb b/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb
index 591ca20093..7dc1b3779f 100644
--- a/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb
+++ b/modules/auxiliary/scanner/winrm/winrm_auth_methods.rb
@@ -27,7 +27,7 @@ class Metasploit3 < Msf::Auxiliary
'Name' => 'WinRM Authentication Method Detection',
'Version' => '$Revision$',
'Description' => %q{
- This module sends a request to a an http/https service to see if it is a WinRM service.
+ This module sends a request to an HTTP/HTTPS service to see if it is a WinRM service.
If it is a WinRM service, it also gathers the Authentication Methods supported.
},
'Author' => [ 'thelightcosine' ],