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)
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
- Branch: main
- Revision: 5ff69e076a8d8cc38707e29d5a8d7c42d5798a8b
- Timestamp: 2026-04-07T13:14:20+00:00
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
- Attacker controls or influences a PKCS#11 module loaded into NSS (malicious smartcard driver, vendor HSM driver bug, or user-loaded PKCS#11 .so).
- Application calls PK11_FindCertsFromURI (or any other code path that ends up in nssCKObject_GetAttributes with a string attribute like CKA_LABEL).
- NSS performs the first C_GetAttributeValue probe to determine the attribute size; the malicious token returns ulValueLen = 0x100000002.
- 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).
- 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.
- Heap-buffer-overflow write -> heap corruption -> potential code execution in the NSS-hosting process.
Steps to Reproduce
- Apply the test patch adding hObject=5 cert3 with CKA_LABEL probe-response ulValueLen = ((CK_ULONG)1 << 32) | 2 to gtests/pkcs11testmodule/pkcs11testmodule.cpp.
- Add Pkcs11ModuleTest.IntegerTruncationCert3LabelOverflow to gtests/pk11_gtest/pk11_module_unittest.cc which calls PK11_FindCertsFromURI on a URI selecting cert3.
- Build NSS with ASan and run pk11_gtest --gtest_filter=Pkcs11ModuleTest.IntegerTruncationCert3LabelOverflow.
- 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
| Reporter | ||
Comment 1•5 months ago
|
||
| Reporter | ||
Comment 2•5 months ago
|
||
| Reporter | ||
Comment 3•5 months ago
|
||
Updated•5 months ago
|
| Assignee | ||
Comment 5•5 months ago
|
||
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.
| Reporter | ||
Comment 6•5 months ago
|
||
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.
| Assignee | ||
Updated•5 months ago
|
| Assignee | ||
Comment 7•5 months ago
|
||
Pushed by jschanck@mozilla.com:
https://hg.mozilla.org/projects/nss/rev/6bf9b38a7525
avoid integer truncation in nssCKObject_GetAttributes. r=nss-reviewers,keeler
Updated•5 months ago
|
| Assignee | ||
Updated•5 months ago
|
Comment 9•5 months ago
|
||
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.
Updated•4 months ago
|
Updated•4 months ago
|
Updated•13 days ago
|
Description
•