1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-09-04 20:18:27 +02:00

Land #4003, @nstarke's Login Scanner for WD MyBook Live NAS

This commit is contained in:
Jon Hart 2014-10-27 09:57:43 -07:00
commit b8c9ef96ca
No known key found for this signature in database
GPG Key ID: 2FA9F0A3AFA8E9D3
3 changed files with 162 additions and 0 deletions

View File

@ -0,0 +1,61 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
# Western Digital MyBook Live login scanner
class MyBookLive < HTTP
# Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP
CAN_GET_SESSION = true
DEFAULT_PORT = 80
PRIVATE_TYPES = [ :password ]
# (see Base#set_sane_defaults)
def set_sane_defaults
self.uri = '/UI/login' if self.uri.nil?
self.method = 'POST' if self.method.nil?
super
end
def attempt_login(credential)
result_opts = {
credential: credential,
host: host,
port: port,
protocol: 'tcp'
}
if ssl
result_opts[:service_name] = 'https'
else
result_opts[:service_name] = 'http'
end
begin
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' => method,
'uri' => uri,
'data' => 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)
elsif res.nil?
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: 'No response')
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res.headers)
end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
end
Result.new(result_opts)
end
end
end
end
end

View File

@ -0,0 +1,91 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/mybook_live'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
def initialize
super(
'Name' => 'Western Digital MyBook Live Login Utility',
'Description' => 'This module simply attempts to login to a Western Digital MyBook Live instance using a specific user/pass.',
'Author' => [ 'Nicholas Starke <starke.nicholas[at]gmail.com>' ],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(80)
], self.class)
register_autofilter_ports([ 80 ])
# username is hardcoded into application
deregister_options('RHOST', 'USERNAME', 'USER_FILE', 'USER_AS_PASS', 'DB_ALL_USERS')
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.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)
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
username: 'admin'
)
scanner = Metasploit::Framework::LoginScanner::MyBookLive.new(
host: ip,
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
connection_timeout: 10,
user_agent: datastore['UserAgent'],
vhost: datastore['VHOST']
)
if ssl
scanner.ssl = datastore['SSL']
scanner.ssl_version = datastore['SSLVERSION']
end
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: fullname,
workspace_id: myworkspace_id
)
if result.success?
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
vprint_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})"
end
end
end
end

View File

@ -0,0 +1,10 @@
require 'spec_helper'
require 'metasploit/framework/login_scanner/mybook_live'
describe Metasploit::Framework::LoginScanner::MyBookLive do
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: false
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
end