Merge pull request #110 from jhartftw/soap_xml_6249
Improvements to auxiiliary/scanner/http/soap_xml to (#6249)unstable
commit
d5443159d7
|
@ -42,7 +42,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
OptString.new('XMLSCHEMA', [ true, "XML Schema", 'http://www.w3.org/2001/XMLSchema']),
|
OptString.new('XMLSCHEMA', [ true, "XML Schema", 'http://www.w3.org/2001/XMLSchema']),
|
||||||
OptString.new('XMLSOAP', [ true, "XML SOAP", 'http://schemas.xmlsoap.org/soap/envelope/']),
|
OptString.new('XMLSOAP', [ true, "XML SOAP", 'http://schemas.xmlsoap.org/soap/envelope/']),
|
||||||
OptString.new('CONTENTTYPE', [ true, "The HTTP Content-Type Header", 'application/x-www-form-urlencoded']),
|
OptString.new('CONTENTTYPE', [ true, "The HTTP Content-Type Header", 'application/x-www-form-urlencoded']),
|
||||||
|
OptInt.new('SLEEP', [true, "Sleep this many seconds between requests", 0 ]),
|
||||||
OptBool.new('DISPLAYHTML', [ true, "Display HTML response", false ]),
|
OptBool.new('DISPLAYHTML', [ true, "Display HTML response", false ]),
|
||||||
|
OptBool.new('SSL', [ true, "Use SSL", false ]),
|
||||||
], self.class)
|
], self.class)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -53,6 +55,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
verbs = [
|
verbs = [
|
||||||
'get',
|
'get',
|
||||||
'active',
|
'active',
|
||||||
|
'activate',
|
||||||
'create',
|
'create',
|
||||||
'change',
|
'change',
|
||||||
'set',
|
'set',
|
||||||
|
@ -74,33 +77,49 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
'register',
|
'register',
|
||||||
'log',
|
'log',
|
||||||
'add',
|
'add',
|
||||||
|
'list',
|
||||||
|
'query',
|
||||||
#'delete', # Best to be safe!
|
#'delete', # Best to be safe!
|
||||||
]
|
]
|
||||||
|
|
||||||
nouns = [
|
nouns = [
|
||||||
'password',
|
'password',
|
||||||
'task',
|
'task',
|
||||||
|
'tasks',
|
||||||
'pass',
|
'pass',
|
||||||
'administration',
|
'administration',
|
||||||
'account',
|
'account',
|
||||||
|
'accounts',
|
||||||
'admin',
|
'admin',
|
||||||
'login',
|
'login',
|
||||||
|
'logins',
|
||||||
'token',
|
'token',
|
||||||
'credentials',
|
'tokens',
|
||||||
'credential',
|
'credential',
|
||||||
|
'credentials',
|
||||||
'key',
|
'key',
|
||||||
|
'keys',
|
||||||
'guid',
|
'guid',
|
||||||
'message',
|
'message',
|
||||||
|
'messages',
|
||||||
'user',
|
'user',
|
||||||
|
'users',
|
||||||
'username',
|
'username',
|
||||||
|
'usernames',
|
||||||
'load',
|
'load',
|
||||||
'list',
|
'list',
|
||||||
'name',
|
'name',
|
||||||
|
'names',
|
||||||
'file',
|
'file',
|
||||||
|
'files',
|
||||||
'path',
|
'path',
|
||||||
|
'paths',
|
||||||
'directory',
|
'directory',
|
||||||
|
'directories',
|
||||||
'configuration',
|
'configuration',
|
||||||
|
'configurations',
|
||||||
'config',
|
'config',
|
||||||
|
'configs',
|
||||||
'setting',
|
'setting',
|
||||||
'settings',
|
'settings',
|
||||||
'registry',
|
'registry',
|
||||||
|
@ -111,79 +130,74 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
target_port = datastore['RPORT']
|
target_port = datastore['RPORT']
|
||||||
vhost = datastore['VHOST'] || wmap_target_host || ip
|
vhost = datastore['VHOST'] || wmap_target_host || ip
|
||||||
|
|
||||||
|
# regular expressions for common rejection messages
|
||||||
|
reject_regexen = []
|
||||||
|
reject_regexen << Regexp.new("method \\S+ is not valid", true)
|
||||||
|
reject_regexen << Regexp.new("Method \\S+ not implemented", true)
|
||||||
|
reject_regexen << Regexp.new("unable to resolve WSDL method name", true)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Check service exists
|
verbs.each do |v|
|
||||||
res = send_request_raw({
|
nouns.each do |n|
|
||||||
'uri' => datastore['PATH'],
|
data_parts = []
|
||||||
'method' => 'GET',
|
data_parts << "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||||
'vhost' => vhost,
|
data_parts << "<soap:Envelope xmlns:xsi=\"#{datastore['XMLINSTANCE']}\" xmlns:xsd=\"#{datastore['XMLSCHEMA']}\" xmlns:soap=\"#{datastore['XMLSOAP']}\">"
|
||||||
}, 10)
|
data_parts << "<soap:Body>"
|
||||||
|
data_parts << "<#{v}#{n} xmlns=\"#{datastore['XMLNAMESPACE']}\">"
|
||||||
|
data_parts << "</#{v}#{n}>"
|
||||||
|
data_parts << "</soap:Body>"
|
||||||
|
data_parts << "</soap:Envelope>"
|
||||||
|
data_parts << nil
|
||||||
|
data_parts << nil
|
||||||
|
data = data_parts.join("\r\n")
|
||||||
|
|
||||||
if (res.code == 200)
|
res = send_request_raw({
|
||||||
print_status("PATH appears to be OK.")
|
'uri' => datastore['PATH'] + '/' + v + n,
|
||||||
|
'method' => 'POST',
|
||||||
|
'vhost' => vhost,
|
||||||
|
'data' => data,
|
||||||
|
'headers' =>
|
||||||
|
{
|
||||||
|
'Content-Length' => data.length,
|
||||||
|
'SOAPAction' => '"' + datastore['XMLNAMESPACE'] + v + n + '"',
|
||||||
|
'Expect' => '100-continue',
|
||||||
|
'Content-Type' => datastore['CONTENTTYPE'],
|
||||||
|
}
|
||||||
|
}, 15)
|
||||||
|
|
||||||
verbs.each do |v|
|
if (res && !(res.body.empty?))
|
||||||
nouns.each do |n|
|
if ((not reject_regexen.select { |r| res.body =~ r }.empty?))
|
||||||
|
print_status("Server rejected SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
|
||||||
# This could be cleaned up - patrickw
|
elsif (res.message =~ /Cannot process the message because the content type/)
|
||||||
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
|
print_status("Server rejected CONTENTTYPE: HTTP: #{res.code} #{res.message}.")
|
||||||
data << '<soap:Envelope xmlns:xsi="' + datastore['XMLINSTANCE'] + '" xmlns:xsd="' + datastore['XMLSCHEMA'] + '" xmlns:soap="' + datastore['XMLSOAP'] + '">' + "\r\n"
|
res.message =~ /was not the expected type\s\'([^']+)'/
|
||||||
data << '<soap:Body>' + "\r\n"
|
print_status("Set CONTENTTYPE to \"#{$1}\"")
|
||||||
data << "<#{v}#{n}" + " xmlns=\"#{datastore['XMLNAMESPACE']}\">" + "\r\n"
|
return false
|
||||||
data << "</#{v}#{n}>" + "\r\n"
|
elsif (res.code == 404)
|
||||||
data << '</soap:Body>' + "\r\n"
|
print_status("Server returned HTTP 404 for #{datastore['PATH']}. Use a different one.")
|
||||||
data << '</soap:Envelope>' + "\r\n\r\n"
|
return false
|
||||||
|
else
|
||||||
res = send_request_raw({
|
print_status("Server responded to SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
|
||||||
'uri' => datastore['PATH'] + '/' + v + n,
|
## Add Report
|
||||||
'method' => 'POST',
|
report_note(
|
||||||
'vhost' => vhost,
|
:host => ip,
|
||||||
'data' => data,
|
:proto => 'tcp',
|
||||||
'headers' =>
|
:sname => (ssl ? 'https' : 'http'),
|
||||||
{
|
:port => rport,
|
||||||
'Content-Length' => data.length,
|
:type => "SOAPAction: #{v}#{n}",
|
||||||
'SOAPAction' => '"' + datastore['XMLNAMESPACE'] + v + n + '"',
|
:data => "SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}."
|
||||||
'Expect' => '100-continue',
|
)
|
||||||
'Content-Type' => datastore['CONTENTTYPE'],
|
if datastore['DISPLAYHTML']
|
||||||
}
|
print_status("The HTML content follows:")
|
||||||
}, 15)
|
print_status(res.body + "\r\n")
|
||||||
|
end
|
||||||
if (res && !(res.body.empty?))
|
end
|
||||||
if (res.body =~ /method name is not valid/)
|
end
|
||||||
print_status("Server rejected SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
|
select(nil, nil, nil, datastore['SLEEP']) if (datastore['SLEEP'] > 0)
|
||||||
elsif (res.message =~ /Cannot process the message because the content type/)
|
end
|
||||||
print_status("Server rejected CONTENTTYPE: HTTP: #{res.code} #{res.message}.")
|
end
|
||||||
res.message =~ /was not the expected type\s\'([^']+)'/
|
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE => e
|
||||||
print_status("Set CONTENTTYPE to \"#{$1}\"")
|
print_error(e)
|
||||||
return false
|
|
||||||
elsif (res.code == 404)
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
print_status("Server responded to SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
|
|
||||||
## Add Report
|
|
||||||
report_note(
|
|
||||||
:host => ip,
|
|
||||||
:proto => 'tcp',
|
|
||||||
:sname => 'HTTP',
|
|
||||||
:port => rport,
|
|
||||||
:type => "SOAPAction: #{v}#{n}",
|
|
||||||
:data => "SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}."
|
|
||||||
)
|
|
||||||
if datastore['DISPLAYHTML']
|
|
||||||
print_status("The HTML content follows:")
|
|
||||||
print_status(res.body + "\r\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
print_status("Server did not respond with 200 OK.")
|
|
||||||
print_status(res.to_s)
|
|
||||||
end
|
|
||||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
|
||||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue