Describe the bug
Vulnerability Basic Information
- Vulnerability Name: OpenSC
pkcs11-tool Key Generation Module Input Validation Flaw Leading to Global Buffer Overflow
- Vulnerability Type: Buffer Overflow (CWE-120 / CWE-787)
- Affected Component: OpenSC (especially the
pkcs11-tool tool)
- Affected Versions: OpenSC 0.26.1 and earlier
- Severity: Medium / High (depending on execution context)
- Attack Vector: Local / Physical
- Prerequisites: The attacker must craft a malicious PKCS#11 module to be loaded by the victim, or provide a malicious physical smart card device with customized firmware, and induce the victim to interact with it via
pkcs11-tool, thereby triggering the test_kpgen_certwrite logic.
Vulnerability Detailed Description
In OpenSC version 0.26.1, within the file src/tools/pkcs11-tool.c, a global buffer overflow vulnerability exists during key pair generation tests such as -z, --test-ec, and --test-kpgen. This vulnerability is caused by missing input validation.
The root cause lies in the function test_kpgen_certwrite(). After dynamically retrieving the CKA_ID attribute returned by the underlying PKCS#11 token or smart card, the function fails to validate the length of the returned data and directly copies it into a fixed-size global static buffer of only 100 bytes.
Vulnerability Code Analysis
1. Fixed-Size Global Buffer Definition
Code Path: src/tools/pkcs11-tool.c : 444
static CK_BYTE opt_object_id[100], new_object_id[100];
static size_t opt_object_id_len = 0, new_object_id_len = 0;
As shown above, the application defines a static array opt_object_id of only 100 bytes to store IDs generated by the smart card.
2. Retrieval of Variable-Length Data from Hardware (Unsafe Trust of Length)
Code Path: src/tools/pkcs11-tool.c : 8387
// After gen_keypair(), retrieve the CKA_ID of the generated private key (length stored in i)
tmp = getID(session, priv_key, &i);
// ... [only check] ...
if (i == 0) {
fprintf(stderr, "ERR: newly generated private key has no (or an empty) CKA_ID\n");
return session;
}
The function getID is a wrapper generated via the VARATTR_METHOD macro, internally invoking the PKCS#11 API C_GetAttributeValue. It dynamically allocates sufficient heap memory based on the length returned by the hardware and stores the length in variable i.
If the underlying token is malicious, it may return excessively large data (e.g., 500, 1000, or more bytes). The current code only checks for i == 0, but performs no upper-bound validation.
3. Triggering the Buffer Overflow
Code Path: src/tools/pkcs11-tool.c : 8392 - 8393
opt_object_id_len = (size_t) i;
memcpy(opt_object_id, tmp, opt_object_id_len); // [!] no bounds checking, overflow occurs
If the returned length exceeds 100 bytes, memcpy will blindly copy all data into opt_object_id, causing an out-of-bounds write.
Since opt_object_id resides in the global .bss segment alongside other global variables, this leads to a classic global buffer overflow, potentially corrupting adjacent global variables, altering program state, or even overwriting function pointers to achieve arbitrary code execution.
Steps to reproduce
Exploitation Scenarios
This vulnerability is not trivial and can be exploited through two realistic attack paths:
Scenario 1: Malicious PKCS#11 Module Injection
This is the most direct and commonly used attack method (also used in our reproduction suite):
- The attacker develops a malicious PKCS#11 shared library (
*.so) implementing APIs such as C_GetAttributeValue.
- The module is disguised as a legitimate driver for a security device and delivered via social engineering.
- The victim is tricked into executing commands such as:
pkcs11-tool --module malicious.so -z xxx
- During execution, the malicious module returns an oversized
CKA_ID, triggering the overflow and enabling potential code execution.
Scenario 2: Malicious Hardware Supply Chain Injection
For high-security enterprise environments:
- The core issue lies in trusting responses from underlying hardware devices.
- An attacker may compromise the supply chain and distribute smart cards with malicious firmware.
- During key generation, the device deliberately returns oversized attribute data.
- When administrators use standard OpenSC tools (e.g.,
pkcs11-tool -z ...) for card initialization or testing, the malicious payload propagates through the hardware interface and triggers the vulnerability, leading to compromise of the host system.
ASan Report and Reproduction Result
In the provided reproduction suite, the malicious module returns a 200-byte CKA_ID. Running the test triggers the following AddressSanitizer report:
=================================================================
==38127==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55e211f35904 at pc 0x7f303c447e93 bp 0x7ffc1d09cf50 sp 0x7ffc1d09c6f8
WRITE of size 200 at 0x55e211f35904 thread T0
#0 0x7f303c447e92 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:899
#1 0x55e211eeb169 in test_kpgen_certwrite /mnt/c/Users/ZHEFOX/Desktop/testcase/OpenSC-0.26.1/src/tools/pkcs11-tool.c:8393
#2 0x55e211eb316a in main /mnt/c/Users/ZHEFOX/Desktop/testcase/OpenSC-0.26.1/src/tools/pkcs11-tool.c:1557
...
0x55e211f35904 is located 0 bytes after global variable 'opt_object_id' defined in 'pkcs11-tool.c:444:17' (0x55e211f358a0) of size 100
0x55e211f35904 is located 60 bytes before global variable 'new_object_id' defined in 'pkcs11-tool.c:444:37' (0x55e211f35940) of size 100
SUMMARY: AddressSanitizer: global-buffer-overflow
Verification Steps
- Download the
<font style="color:rgb(5, 8, 44);">Reproduce2</font> archive from the submission materials.
- Execute the provided script:
- The script compiles
mock_pkcs11.c into mock_pkcs11.so and loads it into an ASan-instrumented pkcs11-tool.
- If a segmentation fault or the above AddressSanitizer error appears, the vulnerability has been successfully reproduced.
Fix Recommendations
This issue stems from improper trust in data returned from lower-level PKCS#11 interfaces (potentially malicious hardware or software modules).
Add Explicit Bounds Checking
Modify pkcs11-tool.c:8387 as follows:
tmp = getID(session, priv_key, &i);
if (i == 0) {
fprintf(stderr, "ERR: newly generated private key has no (or an empty) CKA_ID\n");
return session;
}
// Fix: enforce strict upper bound
if (i > sizeof(opt_object_id)) {
fprintf(stderr, "ERR: returned CKA_ID length (%lu) strictly exceeds maximum supported buffer size (%zu)\n",
(unsigned long)i, sizeof(opt_object_id));
free(tmp);
return session;
}
opt_object_id_len = (size_t) i;
memcpy(opt_object_id, tmp, opt_object_id_len);
Additional Recommendations
- Audit all usages of
C_GetAttributeValue where returned lengths are used in memory copy operations.
- Ensure all buffer operations include strict upper-bound validation.
- Avoid implicit trust in hardware or external module responses.
Reproduction Package
All reproduction materials are included in the Reproduce2 directory.
Expected behavior
pkcs11-tool should validate the length of the CKA_ID attribute returned by the PKCS#11 token or module before copying it into the fixed-size global buffer opt_object_id. If the returned CKA_ID length exceeds the capacity of the destination buffer, the tool should reject the value, report an error, release the allocated memory, and terminate the current operation safely without performing an out-of-bounds write.
Actual behavior
In test_kpgen_certwrite(), after retrieving the CKA_ID of the generated private key, pkcs11-tool only checks whether the returned length is zero, but does not enforce an upper-bound check. The returned length is directly assigned to opt_object_id_len and then used in memcpy(opt_object_id, tmp, opt_object_id_len). When a malicious PKCS#11 module or smart card returns an oversized CKA_ID, the copy operation writes beyond the 100-byte global buffer opt_object_id, triggering a global buffer overflow. In our reproduction, a 200-byte CKA_ID causes AddressSanitizer to report a global-buffer-overflow at src/tools/pkcs11-tool.c:8393.
OpenSC version
OpenSC 0.26.1 and earlier
Operating system
Ubuntu 22.04
Smart card model or security token
No response
Application used with smart card
No response
Logs and debug output
Checklist
Describe the bug
Vulnerability Basic Information
pkcs11-toolKey Generation Module Input Validation Flaw Leading to Global Buffer Overflowpkcs11-tooltool)pkcs11-tool, thereby triggering thetest_kpgen_certwritelogic.Vulnerability Detailed Description
In OpenSC version 0.26.1, within the file
src/tools/pkcs11-tool.c, a global buffer overflow vulnerability exists during key pair generation tests such as-z,--test-ec, and--test-kpgen. This vulnerability is caused by missing input validation.The root cause lies in the function
test_kpgen_certwrite(). After dynamically retrieving theCKA_IDattribute returned by the underlying PKCS#11 token or smart card, the function fails to validate the length of the returned data and directly copies it into a fixed-size global static buffer of only 100 bytes.Vulnerability Code Analysis
1. Fixed-Size Global Buffer Definition
Code Path:
src/tools/pkcs11-tool.c : 444As shown above, the application defines a static array
opt_object_idof only 100 bytes to store IDs generated by the smart card.2. Retrieval of Variable-Length Data from Hardware (Unsafe Trust of Length)
Code Path:
src/tools/pkcs11-tool.c : 8387The function
getIDis a wrapper generated via theVARATTR_METHODmacro, internally invoking the PKCS#11 APIC_GetAttributeValue. It dynamically allocates sufficient heap memory based on the length returned by the hardware and stores the length in variablei.If the underlying token is malicious, it may return excessively large data (e.g., 500, 1000, or more bytes). The current code only checks for
i == 0, but performs no upper-bound validation.3. Triggering the Buffer Overflow
Code Path:
src/tools/pkcs11-tool.c : 8392 - 8393If the returned length exceeds 100 bytes,
memcpywill blindly copy all data intoopt_object_id, causing an out-of-bounds write.Since
opt_object_idresides in the global.bsssegment alongside other global variables, this leads to a classic global buffer overflow, potentially corrupting adjacent global variables, altering program state, or even overwriting function pointers to achieve arbitrary code execution.Steps to reproduce
Exploitation Scenarios
This vulnerability is not trivial and can be exploited through two realistic attack paths:
Scenario 1: Malicious PKCS#11 Module Injection
This is the most direct and commonly used attack method (also used in our reproduction suite):
*.so) implementing APIs such asC_GetAttributeValue.CKA_ID, triggering the overflow and enabling potential code execution.Scenario 2: Malicious Hardware Supply Chain Injection
For high-security enterprise environments:
pkcs11-tool -z ...) for card initialization or testing, the malicious payload propagates through the hardware interface and triggers the vulnerability, leading to compromise of the host system.ASan Report and Reproduction Result
In the provided reproduction suite, the malicious module returns a 200-byte
CKA_ID. Running the test triggers the following AddressSanitizer report:================================================================= ==38127==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55e211f35904 at pc 0x7f303c447e93 bp 0x7ffc1d09cf50 sp 0x7ffc1d09c6f8 WRITE of size 200 at 0x55e211f35904 thread T0 #0 0x7f303c447e92 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:899 #1 0x55e211eeb169 in test_kpgen_certwrite /mnt/c/Users/ZHEFOX/Desktop/testcase/OpenSC-0.26.1/src/tools/pkcs11-tool.c:8393 #2 0x55e211eb316a in main /mnt/c/Users/ZHEFOX/Desktop/testcase/OpenSC-0.26.1/src/tools/pkcs11-tool.c:1557 ... 0x55e211f35904 is located 0 bytes after global variable 'opt_object_id' defined in 'pkcs11-tool.c:444:17' (0x55e211f358a0) of size 100 0x55e211f35904 is located 60 bytes before global variable 'new_object_id' defined in 'pkcs11-tool.c:444:37' (0x55e211f35940) of size 100 SUMMARY: AddressSanitizer: global-buffer-overflowVerification Steps
<font style="color:rgb(5, 8, 44);">Reproduce2</font>archive from the submission materials.mock_pkcs11.cintomock_pkcs11.soand loads it into an ASan-instrumentedpkcs11-tool.Fix Recommendations
This issue stems from improper trust in data returned from lower-level PKCS#11 interfaces (potentially malicious hardware or software modules).
Add Explicit Bounds Checking
Modify
pkcs11-tool.c:8387as follows:Additional Recommendations
C_GetAttributeValuewhere returned lengths are used in memory copy operations.Reproduction Package
All reproduction materials are included in the
Reproduce2directory.Expected behavior
pkcs11-toolshould validate the length of theCKA_IDattribute returned by the PKCS#11 token or module before copying it into the fixed-size global bufferopt_object_id. If the returnedCKA_IDlength exceeds the capacity of the destination buffer, the tool should reject the value, report an error, release the allocated memory, and terminate the current operation safely without performing an out-of-bounds write.Actual behavior
In
test_kpgen_certwrite(), after retrieving theCKA_IDof the generated private key,pkcs11-toolonly checks whether the returned length is zero, but does not enforce an upper-bound check. The returned length is directly assigned toopt_object_id_lenand then used inmemcpy(opt_object_id, tmp, opt_object_id_len). When a malicious PKCS#11 module or smart card returns an oversizedCKA_ID, the copy operation writes beyond the 100-byte global bufferopt_object_id, triggering a global buffer overflow. In our reproduction, a 200-byteCKA_IDcauses AddressSanitizer to report aglobal-buffer-overflowatsrc/tools/pkcs11-tool.c:8393.OpenSC version
OpenSC 0.26.1 and earlier
Operating system
Ubuntu 22.04
Smart card model or security token
No response
Application used with smart card
No response
Logs and debug output
Checklist