Merge pull request #110 from jhartftw/soap_xml_6249

Improvements to auxiiliary/scanner/http/soap_xml to (#6249)
unstable
sinn3r 2012-01-16 18:19:33 -08:00
commit d5443159d7
1 changed files with 85 additions and 71 deletions

View File

@ -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