From ce8a9941ea301d9e69a4ee1d9a9ad6a422f466b5 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Wed, 22 Oct 2014 10:36:24 -0700 Subject: [PATCH 1/2] Cleanup. Sanity check in setup. vprint --- .../framework/login_scanner/mybook_live.rb | 16 ++++++------ .../scanner/http/mybook_live_login.rb | 26 ++++++++++++------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/mybook_live.rb b/lib/metasploit/framework/login_scanner/mybook_live.rb index 0c34cf6bc9..65a44d255f 100644 --- a/lib/metasploit/framework/login_scanner/mybook_live.rb +++ b/lib/metasploit/framework/login_scanner/mybook_live.rb @@ -22,10 +22,10 @@ module Metasploit def attempt_login(credential) result_opts = { - credential: credential, - host: host, - port: port, - protocol: 'tcp' + credential: credential, + host: host, + port: port, + protocol: 'tcp' } if ssl result_opts[:service_name] = 'https' @@ -33,14 +33,14 @@ module Metasploit result_opts[:service_name] = 'http' end begin - body = "data%5BLogin%5D%5Bowner_name%5D=admin&data%5BLogin%5D%5Bowner_passwd%5D=#{Rex::Text.uri_encode(credential.private)}" + body = "data[Login][owner_name]=admin&data[Login][owner_passwd]=#{credential.private}" cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version) cli.connect - req = cli.request_cgi({ + req = cli.request_cgi( 'method' => 'POST', 'uri' => '/UI/login', - 'data' => body - }) + 'data' => Rex::Text.uri_encode(body) + ) res = cli.send_recv(req) if res && res.code == 302 && res.headers['location'] && res.headers['location'].include?('UI') result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.headers) diff --git a/modules/auxiliary/scanner/http/mybook_live_login.rb b/modules/auxiliary/scanner/http/mybook_live_login.rb index 975b3a2014..1ba0c9ee6f 100644 --- a/modules/auxiliary/scanner/http/mybook_live_login.rb +++ b/modules/auxiliary/scanner/http/mybook_live_login.rb @@ -27,17 +27,25 @@ class Metasploit3 < Msf::Auxiliary ], self.class) register_autofilter_ports([ 80 ]) - - #username is hardcoded into application + + # username is hardcoded into application deregister_options('RHOST', 'USERNAME', 'USER_FILE', 'USER_AS_PASS', 'DB_ALL_USERS') end + def setup + # They must select at least blank passwords, provide a pass file or a password + one_required = %w(BLANK_PASSWORDS PASS_FILE PASSWORD) + unless one_required.any? { |o| datastore[o] } + fail_with(Failure::BadConfig, "Invalid options: One of #{one_required.join(', ')} must be set") + end + end + def run_host(ip) cred_collection = Metasploit::Framework::CredentialCollection.new( - blank_passwords: datastore['BLANK_PASSWORDS'], - pass_file: datastore['PASS_FILE'], - password: datastore['PASSWORD'], - username: 'admin' + blank_passwords: datastore['BLANK_PASSWORDS'], + pass_file: datastore['PASS_FILE'], + password: datastore['PASSWORD'], + username: 'admin' ) scanner = Metasploit::Framework::LoginScanner::MyBookLive.new( @@ -59,8 +67,8 @@ class Metasploit3 < Msf::Auxiliary scanner.scan! do |result| credential_data = result.to_h credential_data.merge!( - module_fullname: fullname, - workspace_id: myworkspace_id + module_fullname: fullname, + workspace_id: myworkspace_id ) if result.success? credential_core = create_credential(credential_data) @@ -70,7 +78,7 @@ class Metasploit3 < Msf::Auxiliary print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}" else invalidate_login(credential_data) - print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})" + vprint_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})" end end end From 83df08aaa7cfc18cf3bbd59aba009a0a177cc040 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Wed, 22 Oct 2014 22:43:06 -0700 Subject: [PATCH 2/2] Properly encode body and catch invalid configs --- lib/metasploit/framework/login_scanner/mybook_live.rb | 5 +++-- modules/auxiliary/scanner/http/mybook_live_login.rb | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/mybook_live.rb b/lib/metasploit/framework/login_scanner/mybook_live.rb index 65a44d255f..ad8fbb12bb 100644 --- a/lib/metasploit/framework/login_scanner/mybook_live.rb +++ b/lib/metasploit/framework/login_scanner/mybook_live.rb @@ -33,13 +33,14 @@ module Metasploit result_opts[:service_name] = 'http' end begin - body = "data[Login][owner_name]=admin&data[Login][owner_passwd]=#{credential.private}" + cred = Rex::Text.uri_encode(credential.private) + body = "data%5BLogin%5D%5Bowner_name%5D=admin&data%5BLogin%5D%5Bowner_passwd%5D=#{cred}" cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version) cli.connect req = cli.request_cgi( 'method' => 'POST', 'uri' => '/UI/login', - 'data' => Rex::Text.uri_encode(body) + 'data' => body ) res = cli.send_recv(req) if res && res.code == 302 && res.headers['location'] && res.headers['location'].include?('UI') diff --git a/modules/auxiliary/scanner/http/mybook_live_login.rb b/modules/auxiliary/scanner/http/mybook_live_login.rb index 1ba0c9ee6f..458f51dffb 100644 --- a/modules/auxiliary/scanner/http/mybook_live_login.rb +++ b/modules/auxiliary/scanner/http/mybook_live_login.rb @@ -33,11 +33,17 @@ class Metasploit3 < Msf::Auxiliary end def setup + super # They must select at least blank passwords, provide a pass file or a password one_required = %w(BLANK_PASSWORDS PASS_FILE PASSWORD) - unless one_required.any? { |o| datastore[o] } + unless one_required.any? { |o| datastore.has_key?(o) && datastore[o] } fail_with(Failure::BadConfig, "Invalid options: One of #{one_required.join(', ')} must be set") end + if !datastore['PASS_FILE'] + if !datastore['BLANK_PASSWORDS'] && datastore['PASSWORD'].blank? + fail_with(Failure::BadConfig, "PASSWORD or PASS_FILE must be set to a non-empty string if not BLANK_PASSWORDS") + end + end end def run_host(ip)