Closed Bug 2030374 Opened 5 months ago Closed 5 months ago

Heap buffer overflow in [@ nssCKObject_GetAttributes] due to CK_ULONG to PRUint32 truncation in nss_ZAlloc size

Categories

(NSS :: Libraries, defect, P2)

Tracking

(nss 3.124, firefox-esr115 wontfix, firefox-esr140 wontfix, firefox150 wontfix, firefox151 wontfix, firefox152 fixed)

RESOLVED FIXED
Tracking Status
nss --- 3.124
firefox-esr115 --- wontfix
firefox-esr140 --- wontfix
firefox150 --- wontfix
firefox151 --- wontfix
firefox152 --- fixed

People

(Reporter: bugmon, Assigned: jschanck)

Details

(5 keywords, Whiteboard: [adv-main152+r])

Attachments

(4 files)

nssCKObject_GetAttributes() in lib/dev/ckhelper.c queries a PKCS#11 token for the size of each attribute via C_GetAttributeValue and stores the returned size in a local CK_ULONG (64 bits on 64-bit platforms). It then passes that size to nss_ZAlloc(NSSArena*, PRUint32), which silently truncates the value to 32 bits. The second C_GetAttributeValue call uses the un-truncated CK_ULONG ulValueLen still present in the template entry to write the full attribute payload. If a token returns a length whose low 32 bits are small but whose upper 32 bits are non-zero (e.g. 0x100000002), NSS allocates a tiny buffer (here 19 bytes for a string-typed attribute, low 32 bits + 1 NUL) yet the token writes the full-length payload, producing a heap-buffer-overflow write.

The vulnerable path is reachable through the public API PK11_FindCertsFromURI -> find_certs_from_uri -> nssToken_FindObjectsByTemplate -> create_objects_from_handles -> nssCryptokiObject_Create (arenaOpt=NULL) -> nssCKObject_GetAttributes, with a CKA_LABEL probe triggering the string +1 path. The attacker model is a malicious or buggy PKCS#11 module (smartcard driver, HSM driver, attacker-supplied .so loaded by the user, or vendor token misbehavior). Such modules are part of NSS's normal loadable-token threat surface.

Build Info

Affected Code

File: security/nss/lib/dev/ckhelper.c, line 94-109

for (i = 0; i < count; i++) {
    CK_ULONG ulValueLen = obj_template[i].ulValueLen;
    if (ulValueLen == 0 || ulValueLen == (CK_ULONG)-1) {
        obj_template[i].pValue = NULL;
        obj_template[i].ulValueLen = 0;
        continue;
    }
    if (is_string_attribute(obj_template[i].type)) {
        ulValueLen++;
    }
    obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen); /* PRUint32 truncation */
    if (!obj_template[i].pValue) {
        nssSession_ExitMonitor(session);
        goto loser;
    }
}

File: security/nss/lib/base/base.h, line 274

NSS_EXTERN void *nss_ZAlloc(NSSArena *arenaOpt, PRUint32 size);

nss_ZAlloc's size parameter is a 32-bit PRUint32 while ulValueLen is a 64-bit CK_ULONG. The truncation happens at the call boundary; the obj_template[i].ulValueLen field retains its original 64-bit value, which is then used by the subsequent C_GetAttributeValue call to copy the full attribute data into the undersized buffer.

Exploit Chain

  1. Attacker controls or influences a PKCS#11 module loaded into NSS (malicious smartcard driver, vendor HSM driver bug, or user-loaded PKCS#11 .so).
  2. Application calls PK11_FindCertsFromURI (or any other code path that ends up in nssCKObject_GetAttributes with a string attribute like CKA_LABEL).
  3. NSS performs the first C_GetAttributeValue probe to determine the attribute size; the malicious token returns ulValueLen = 0x100000002.
  4. nssCKObject_GetAttributes loads ulValueLen into a CK_ULONG local, increments it (string attribute), then passes it to nss_ZAlloc which truncates it to 0x00000003 (or similar low-32-bit value), allocating a tiny buffer (19 bytes in the reproducer).
  5. NSS performs the second C_GetAttributeValue with obj_template[i].ulValueLen still equal to the full untruncated CK_ULONG; the token writes the entire payload into the small heap buffer, corrupting adjacent heap memory.
  6. Heap-buffer-overflow write -> heap corruption -> potential code execution in the NSS-hosting process.

Steps to Reproduce

  1. Apply the test patch adding hObject=5 cert3 with CKA_LABEL probe-response ulValueLen = ((CK_ULONG)1 << 32) | 2 to gtests/pkcs11testmodule/pkcs11testmodule.cpp.
  2. Add Pkcs11ModuleTest.IntegerTruncationCert3LabelOverflow to gtests/pk11_gtest/pk11_module_unittest.cc which calls PK11_FindCertsFromURI on a URI selecting cert3.
  3. Build NSS with ASan and run pk11_gtest --gtest_filter=Pkcs11ModuleTest.IntegerTruncationCert3LabelOverflow.
  4. Observe AddressSanitizer heap-buffer-overflow with allocation frame at lib/dev/ckhelper.c:104 and write originating from lib/dev/ckhelper.c:113.

Security Impact

  • Severity: High
  • Attacker capability: Heap-buffer-overflow write of attacker-controlled length and contents into the NSS-host process heap. With careful heap shaping this is exploitable for memory corruption and likely code execution in the process loading NSS.
  • Preconditions: Attacker must be able to cause NSS to load a PKCS#11 module that returns crafted attribute lengths. This includes malicious smartcard/HSM drivers, vendor PKCS#11 modules with bugs, or any scenario where a user is convinced to install/configure a hostile PKCS#11 .so. No additional renderer or sandbox compromise is required.

ASAN Report

==17089==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x50300068e733 at pc 0x790a474b9303
WRITE of size 20 at 0x50300068e733 thread T0
    #0 memcpy sanitizer_common_interceptors_memintrinsics.inc:115
    #1 Test_C_GetAttributeValue gtests/pkcs11testmodule/pkcs11testmodule.cpp:438
    #2 nssCKObject_GetAttributes lib/dev/ckhelper.c:113
    #3 nssCryptokiObject_Create lib/dev/devutil.c:32
    #4 create_objects_from_handles lib/dev/devtoken.c:220
    #5 find_objects lib/dev/devtoken.c:324
    #6 nssToken_FindObjectsByTemplate lib/dev/devtoken.c:413
    #7 find_certs_from_uri lib/pk11wrap/pk11cert.c:783
    #8 PK11_FindCertsFromURI lib/pk11wrap/pk11cert.c:834

0x50300068e733 is located 0 bytes after 19-byte region [0x50300068e720,0x50300068e733)
allocated by thread T0 here:
    #0 calloc asan_malloc_linux.cpp:77
    #1 PR_Calloc prmem.c:434
    #2 nss_ZAlloc lib/base/arena.c:835
    #3 nssCKObject_GetAttributes lib/dev/ckhelper.c:104
    #4 nssCryptokiObject_Create lib/dev/devutil.c:32
    #5 create_objects_from_handles lib/dev/devtoken.c:220
    #6 find_objects lib/dev/devtoken.c:324
    #7 nssToken_FindObjectsByTemplate lib/dev/devtoken.c:413
    #8 find_certs_from_uri lib/pk11wrap/pk11cert.c:783
    #9 PK11_FindCertsFromURI lib/pk11wrap/pk11cert.c:834
Attached file pkcs11testmodule.cpp —
Attached file crash_stack.txt —
Group: core-security → crypto-core-security

Downgrading to sec-moderate as this is outside the typical threat model for Firefox. An attacker who has convinced the user to load a malicious PKCS#11 module already has the capability to run arbitrary code in the parent process.

Severity: -- → S3
Status: UNCONFIRMED → NEW
Ever confirmed: true
Keywords: sec-high → sec-moderate
Priority: -- → P2

Unable to reproduce bug 2030374 using build mozilla-central 20260408160318-3cb9ee69178b. Without a baseline, bugmon is unable to analyze this bug.
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.

Keywords: bugmon
Assignee: nobody → jschanck
Attached file (secure) —

Pushed by jschanck@mozilla.com:
https://hg.mozilla.org/projects/nss/rev/6bf9b38a7525
avoid integer truncation in nssCKObject_GetAttributes. r=nss-reviewers,keeler

Status: NEW → RESOLVED
Closed: 5 months ago
Resolution: --- → FIXED
Group: crypto-core-security → core-security-release
status-nss: --- → 3.124

The patch protects against improperly encoded PKCS #11 modules. As John noted, a malicious PKCS #11 module already has full control of your address space and can already compromise your process.

QA Whiteboard: [sec] [qa-triage-done-c153/b152]
Whiteboard: [adv-main152+r]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: