## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report # Huge thanks to @zeroSteiner for helping me. Also thanks to @kaospunk. Finally thanks to # Joomscan and various MSF modules for code examples. def initialize super( 'Name' => 'Joomla Page Scanner', 'Description' => %q{ This module scans a Joomla install for common pages. }, 'Author' => [ 'newpid0' ], 'License' => MSF_LICENSE ) register_options( [ OptString.new('TARGETURI', [ true, "The path to the Joomla install", '/']) ], self.class) end def peer return "#{rhost}:#{rport}" end def run_host(ip) tpath = normalize_uri(target_uri.path) if tpath[-1,1] != '/' tpath += '/' end pages = [ 'robots.txt', 'administrator/index.php', 'admin/', 'index.php/using-joomla/extensions/components/users-component/registration-form', 'index.php/component/users/?view=registration', 'htaccess.txt' ] vprint_status("#{peer} - Checking for interesting pages") pages.each do |page| scan_pages(tpath, page, ip) end end def scan_pages(tpath, page, ip) res = send_request_cgi({ 'uri' => "#{tpath}#{page}", 'method' => 'GET', }) return if not res or not res.body or not res.code res.body.gsub!(/[\r|\n]/, ' ') if (res.code == 200) note = "Page Found" if (res.body =~ /Administration Login/ and res.body =~ /\(\'form-login\'\)\.submit/ or res.body =~/administration console/) note = "Administrator Login Page" elsif (res.body =~/Registration/ and res.body =~/class="validate">Register<\/button>/) note = "Registration Page" end print_good("#{peer} - #{note}: #{tpath}#{page}") report_note( :host => ip, :port => datastore['RPORT'], :proto => 'http', :ntype => 'joomla_page', :data => "#{note}: #{tpath}#{page}", :update => :unique_data ) elsif (res.code == 403) if (res.body =~ /secured with Secure Sockets Layer/ or res.body =~ /Secure Channel Required/ or res.body =~ /requires a secure connection/) vprint_status("#{ip} denied access to #{ip} (SSL Required)") elsif (res.body =~ /has a list of IP addresses that are not allowed/) vprint_status("#{ip} restricted access by IP") elsif (res.body =~ /SSL client certificate is required/) vprint_status("#{ip} requires a SSL client certificate") else vprint_status("#{ip} ip access to #{ip} #{res.code} #{res.message}") end end return rescue OpenSSL::SSL::SSLError vprint_error("#{peer} - SSL error") return rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError vprint_error("#{peer} - Unable to Connect") return rescue ::Timeout::Error, ::Errno::EPIPE vprint_error("#{peer} - Timeout error") return end end