Merge branch 'WinRM_piecemeal' of git://github.com/dmaloney-r7/metasploit-framework into dmaloney-r7-WinRM_piecemeal
commit
f71f83095b
|
@ -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,136 +181,22 @@ 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 = "<w:OptionSet>"
|
||||
options.each do |option_pair|
|
||||
xml << winrm_option(*option_pair)
|
||||
end
|
||||
xml << "</w:OptionSet>"
|
||||
return xml
|
||||
end
|
||||
def winrm_option(name,value)
|
||||
%Q{<w:Option Name="#{name}">#{value}</w:Option>}
|
||||
end
|
||||
def winrm_selector_set(selectors)
|
||||
xml = "<w:SelectorSet>"
|
||||
selectors.each do |selector_pair|
|
||||
xml << winrm_selector(*selector_pair)
|
||||
end
|
||||
xml << "</w:SelectorSet>"
|
||||
return xml
|
||||
end
|
||||
def winrm_selector(name,value)
|
||||
%Q{<w:Selector Name="#{name}">#{value}</w:Selector>}
|
||||
end
|
||||
def winrm_wql_body(wql)
|
||||
%Q{
|
||||
<env:Body>
|
||||
<n:Enumerate>
|
||||
<w:OptimizeEnumeration xsi:nil="true"/>
|
||||
<w:MaxElements>32000</w:MaxElements>
|
||||
<w:Filter Dialect="http://schemas.microsoft.com/wbem/wsman/1/WQL">#{wql}</w:Filter>
|
||||
</n:Enumerate>
|
||||
</env:Body>
|
||||
}
|
||||
end
|
||||
def winrm_open_shell_body
|
||||
%q{<env:Body>
|
||||
<rsp:Shell>
|
||||
<rsp:InputStreams>stdin</rsp:InputStreams>
|
||||
<rsp:OutputStreams>stdout stderr</rsp:OutputStreams>
|
||||
</rsp:Shell>
|
||||
</env:Body>}
|
||||
end
|
||||
def winrm_cmd_body(cmd)
|
||||
%Q{ <env:Body>
|
||||
<rsp:CommandLine>
|
||||
<rsp:Command>"#{cmd}"</rsp:Command>
|
||||
</rsp:CommandLine>
|
||||
</env:Body>}
|
||||
end
|
||||
def winrm_cmd_recv_body(cmd_id)
|
||||
%Q{<env:Body>
|
||||
<rsp:Receive>
|
||||
<rsp:DesiredStream CommandId="#{cmd_id}">stdout stderr</rsp:DesiredStream>
|
||||
</rsp:Receive>
|
||||
</env:Body>}
|
||||
end
|
||||
def winrm_terminate_cmd_body(cmd_id)
|
||||
%Q{ <env:Body>
|
||||
<rsp:Signal CommandId="#{cmd_id}">
|
||||
<rsp:Code>http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate</rsp:Code>
|
||||
</rsp:Signal>
|
||||
</env:Body>}
|
||||
end
|
||||
def winrm_empty_body
|
||||
%q{<env:Body/>}
|
||||
end
|
||||
def winrm_envelope(data)
|
||||
%Q{
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<env:Envelope xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:b="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
|
||||
xmlns:cfg="http://schemas.microsoft.com/wbem/wsman/1/config" xmlns:env="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd"
|
||||
xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
|
||||
xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> #{data}</env:Envelope>
|
||||
}
|
||||
end
|
||||
def winrm_header(data)
|
||||
%Q{
|
||||
<env:Header>
|
||||
<a:To>#{target_url}</a:To>
|
||||
<a:ReplyTo>
|
||||
<a:Address mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
|
||||
</a:ReplyTo>
|
||||
<w:MaxEnvelopeSize mustUnderstand="true">153600</w:MaxEnvelopeSize>
|
||||
<a:MessageID>uuid:#{generate_uuid}</a:MessageID>
|
||||
<w:Locale mustUnderstand="false" xml:lang="en-US"/>
|
||||
<p:DataLocale mustUnderstand="false" xml:lang="en-US"/>
|
||||
<w:OperationTimeout>PT60S</w:OperationTimeout>
|
||||
#{data}
|
||||
</env:Header>
|
||||
}
|
||||
end
|
||||
def winrm_uri_action(type)
|
||||
case type
|
||||
when "wql"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action>}
|
||||
when "create_shell"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action>}
|
||||
when "send_cmd"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command</a:Action>}
|
||||
when "recv_cmd"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive</a:Action>}
|
||||
when "signal_shell"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal</a:Action>}
|
||||
when "delete_shell"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action>}
|
||||
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)
|
||||
opts = {
|
||||
'uri' => datastore['URI'],
|
||||
'data' => data,
|
||||
'username' => datastore['USERNAME'],
|
||||
'password' => datastore['PASSWORD']
|
||||
}
|
||||
'uri' => datastore['URI'],
|
||||
'data' => data,
|
||||
'username' => datastore['USERNAME'],
|
||||
'password' => datastore['PASSWORD']
|
||||
}
|
||||
ntlm_options = {
|
||||
:signing => false,
|
||||
:usentlm2_session => datastore['NTLM::UseNTLM2_session'],
|
||||
|
@ -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 = "<w:OptionSet>"
|
||||
options.each do |option_pair|
|
||||
xml << winrm_option(*option_pair)
|
||||
end
|
||||
xml << "</w:OptionSet>"
|
||||
return xml
|
||||
end
|
||||
|
||||
def winrm_option(name,value)
|
||||
%Q{<w:Option Name="#{name}">#{value}</w:Option>}
|
||||
end
|
||||
|
||||
def winrm_selector_set(selectors)
|
||||
xml = "<w:SelectorSet>"
|
||||
selectors.each do |selector_pair|
|
||||
xml << winrm_selector(*selector_pair)
|
||||
end
|
||||
xml << "</w:SelectorSet>"
|
||||
return xml
|
||||
end
|
||||
|
||||
def winrm_selector(name,value)
|
||||
%Q{<w:Selector Name="#{name}">#{value}</w:Selector>}
|
||||
end
|
||||
|
||||
def winrm_wql_body(wql)
|
||||
%Q{
|
||||
<env:Body>
|
||||
<n:Enumerate>
|
||||
<w:OptimizeEnumeration xsi:nil="true"/>
|
||||
<w:MaxElements>32000</w:MaxElements>
|
||||
<w:Filter Dialect="http://schemas.microsoft.com/wbem/wsman/1/WQL">#{wql}</w:Filter>
|
||||
</n:Enumerate>
|
||||
</env:Body>
|
||||
}
|
||||
end
|
||||
|
||||
def winrm_open_shell_body
|
||||
%q{<env:Body>
|
||||
<rsp:Shell>
|
||||
<rsp:InputStreams>stdin</rsp:InputStreams>
|
||||
<rsp:OutputStreams>stdout stderr</rsp:OutputStreams>
|
||||
</rsp:Shell>
|
||||
</env:Body>}
|
||||
end
|
||||
|
||||
def winrm_cmd_body(cmd)
|
||||
%Q{ <env:Body>
|
||||
<rsp:CommandLine>
|
||||
<rsp:Command>"#{cmd}"</rsp:Command>
|
||||
</rsp:CommandLine>
|
||||
</env:Body>}
|
||||
end
|
||||
|
||||
def winrm_cmd_recv_body(cmd_id)
|
||||
%Q{<env:Body>
|
||||
<rsp:Receive>
|
||||
<rsp:DesiredStream CommandId="#{cmd_id}">stdout stderr</rsp:DesiredStream>
|
||||
</rsp:Receive>
|
||||
</env:Body>}
|
||||
end
|
||||
|
||||
def winrm_terminate_cmd_body(cmd_id)
|
||||
%Q{ <env:Body>
|
||||
<rsp:Signal CommandId="#{cmd_id}">
|
||||
<rsp:Code>http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate</rsp:Code>
|
||||
</rsp:Signal>
|
||||
</env:Body>}
|
||||
end
|
||||
|
||||
def winrm_empty_body
|
||||
%q{<env:Body/>}
|
||||
end
|
||||
|
||||
def winrm_envelope(data)
|
||||
%Q{
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<env:Envelope xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:b="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
|
||||
xmlns:cfg="http://schemas.microsoft.com/wbem/wsman/1/config" xmlns:env="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd"
|
||||
xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
|
||||
xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> #{data}</env:Envelope>
|
||||
}
|
||||
end
|
||||
|
||||
def winrm_header(data)
|
||||
%Q{
|
||||
<env:Header>
|
||||
<a:To>#{target_url}</a:To>
|
||||
<a:ReplyTo>
|
||||
<a:Address mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
|
||||
</a:ReplyTo>
|
||||
<w:MaxEnvelopeSize mustUnderstand="true">153600</w:MaxEnvelopeSize>
|
||||
<a:MessageID>uuid:#{generate_uuid}</a:MessageID>
|
||||
<w:Locale mustUnderstand="false" xml:lang="en-US"/>
|
||||
<p:DataLocale mustUnderstand="false" xml:lang="en-US"/>
|
||||
<w:OperationTimeout>PT60S</w:OperationTimeout>
|
||||
#{data}
|
||||
</env:Header>
|
||||
}
|
||||
end
|
||||
|
||||
def winrm_uri_action(type)
|
||||
case type
|
||||
when "wql"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action>}
|
||||
when "create_shell"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action>}
|
||||
when "send_cmd"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command</a:Action>}
|
||||
when "recv_cmd"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive</a:Action>}
|
||||
when "signal_shell"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal</a:Action>}
|
||||
when "delete_shell"
|
||||
return %q{<w:ResourceURI mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd</w:ResourceURI>
|
||||
<a:Action mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action>}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,10 +24,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'WinRM Authentication Methos Detection',
|
||||
'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' ],
|
||||
|
|
Loading…
Reference in New Issue