Headline
CVE-2022-48332: Cyber Intelligence - Hardware and Software Security Assessments
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys file_name_len integer overflow and resultant buffer overflow.
CVE-2022-48332:
Buffer Overflow in Widevine Trustlet (drm_save_keys @ 0x6a18)
CVE:
CVE-2022-48332
Vendor:
Device:
Nexus 6
Affected Component:
Widevine
Publication Date:
March 2023
Credits:
CyberIntel Team
Last edited: 11/04/23
1. Description
This entry describes a vulnerability that we found in the Widevine Trusted Application (TA), which runs within Qualcomm’s Secure Execution Environment (QSEE). The vulnerability is an integer overflow that leads to a subsequent buffer overflow. This bug has been found using tools we have developed to assist in the security evaluation of TrustZone, including a debugger and a coverage-based fuzzer for QSEE TAs. Please, refer to this page for further information.
Qualcomm Secure Execution Environment is one of the most widespread commercial TEE solutions in the smartphone space, used by many different devices such as Xiaomi, Motorola and several devices of the Google Nexus and Pixel series.
Widevine is a Digital Rights Management (DRM) technology developed by Google to protect copyrighted content and to enable secure distribution and consumption of video and audio content. The technology involves encryption, licensing, and key management to ensure that content can only be decrypted and played back on authorized devices.
An attacker could potentially exploit the vulnerability in the Trusted Application by sending a command from the Normal World, causing the application to crash and possibly execute arbitrary code. This vulnerability could have potential consequences, such as elevating attacker’s privileges and exposing sensitive information.
This post is part of a series of related bugs affecting Widevine Trusted Application of Google Nexus 6:
CVE-2022-48331
CVE-2022-48332
CVE-2022-48333
CVE-2022-48334
CVE-2022-48335
CVE-2022-48336
CVE-2015-6639
CVE-2015-6647
2. Affected Versions
Affected versions are: 5.0.0 (LRX21O), 5.0.1 (LRX22C), 5.1.0 (LMY47D), 5.1.0 (LMY47E), 5.1.0 (LMY47I), 5.1.0 (LMY47M), 5.1.1 (LMY47Z), 5.1.1 (LMY48I), 5.1.1 (LMY48M), 5.1.1 (LMY48T), 5.1.1 (LMY48W), 5.1.1 (LMY48X), 5.1.1 (LMY48Y), 5.1.1 (LVY48C), 5.1.1 (LVY48E), 5.1.1 (LVY48F), 5.1.1 (LVY48H), 5.1.1 (LVY48I), 5.1.1 (LYZ28E), 5.1.1 (LYZ28J), 5.1.1 (LYZ28K), 5.1.1 (LYZ28M) and 5.1.1 (LYZ28N).
3. Impact
This vulnerability has the potential to compromise the security of the system in multiple ways.
An attacker with high priviledges in Normal World can exploit the vulnerability to compromise the Trusted Application running in the Secure World, eventually executing arbitrary code and reading and/or modifying information of critical files, compromising the confidentiality and integrity of the system.
On the other hand, the attacker is able to crash the Trusted Application, potentially resulting in a denial of service.
4. Vulnerability
The bug is present in Widevine’s drm_save_keys() command. This command closely resembles drm_verify_keys(), which has been featured in other blog entries (refer to CVE-2022-48333 and CVE-2022-48334).
The following snippet shows a switch-case present in the TA’s command handler:
switch(*req_buf) { case 0x50001: // drm_save_keys() command if ((0x2a10 < req_buf_size) && (0x107 < resp_buf_size)) { … drm_save_keys( req_buf + 4, req_buf[1], // feature_name req_buf + 0x44, req_buf[2], // file_name req_buf + 0x84, req_buf[3], // msg resp_buf + 4 // prt_path (result) ); } break; }
It takes the Command ID from the first word of the Request Buffer, which is sent by client applications in the Normal World. Thus, if the received command is 0x50001, it jumps to the drm_save_keys() function.
The structure of the Request Buffer for this command is the following:
struct widevine_drm_save_keys_cmd { uint32_t cmd_id; uint32_t feature_name_len; uint32_t file_name_len; uint32_t msg_len; char feature_name[0x100]; char file_name[0x100]; char msg_data[0x100]; };
It contains three buffers (i.e., feature_name, file_name and msg_data) and three integers indicating the effective length of each buffer. It is important to note that even though the maximum size of each buffer is 256 bytes, the client has control over the values of feature_name_len, file_name_len and msg_len, since they are directly taken from the Request Buffer.
The main functionality of drm_save_keys() is securely storing encryption keys or DRM-related data. It performs the following high-level tasks:
Validate input parameters and check for any constraints that may prevent key storage.
Construct a file path using the provided feature name and file name.
Write the message data, which may contain encryption keys or DRM-related information, to a Secure File System (SFS).
Compute and store a CRC value for the written data to ensure data integrity and error detection.
The bug is present in the validation of input parameters while constructing the SFS file path:
heap_buf = malloc(0x100); … memzero(heap_buf, 0x80); prefix_len = strncpy(heap_buf, &persist_prefix, 0x80); total_len = prefix_len + feature_name_len; // ---- CVE-2022-48331 ---- // if (total_len < 0x100) { prefix_len = strlen(&persist_prefix); memcpy(heap_buf + prefix_len, feature_name, feature_name_len); // ----------------------- // *(heap_buf + total_len) = '/’; if (total_len + feature_name_len < 0xff) { memcpy(heap_buf + total_len + 1, feature_name, feature_name_len); total_len += (feature_name_len + 1); *(heap_buf + total_len) = '/’; // ---- CVE-2022-48332 ---- // if (total_len + file_name_len < 0xff) { memcpy(heap_buf + total_len + 1, file_name, file_name_len); … }
In this code snippet, a heap buffer is allocated and the persist_prefix string is copied into it using the strncpy() function. This string is initialized with the value “/persist/data/” by default, so that it’s length is 14. The buffer is then filled with the provided feature name, ensuring the total length does not exceed the specified limit. This is done using total_len by adding the length of the persist_prefix string and feature_name_len, which is directly specified by the client through the Request Buffer.
The first part corresponds to CVE-2022-48331, where the check if (total_len < 0x100) is performed using a signed integer and can cause a buffer overflow if feature_name_len takes any value from -14 (0xfffffff2) to -1 (0xffffffff).
To pass this first check without triggering the first bug, the value of feature_name_len must be within the inclusive range of 1 to 241. Then, the code appends the feature_name string two times to the temporary heap buffer. In the previous code snippet, there is a second check on feature_name_len that constraints its value to [1, 120]. Finally, there is a third if that checks the value of file_name_len. At this point, the result of the addition is treated as a signed integer, which leads to an incorrect check. Consequently, this third check is bypassed when the values for file_name_len are sufficiently large:
req.feature_name_len = 120; // valid values are: [1, 120] req.file_name_len = -(14 + (2 * req.feature_name_len) + 1);
The code after the check calls the memcpy() function to copy the contents of the file_name string into the heap buffer, using the improperly checked file_name_len. Since this value can be large enough, it can cause a buffer overflow in this copy operation:
The user has full control over the value of file_name_len and the contents of the file_name buffer in the Request Buffer.
Since there are several specific and large file_name_len values that can cause the buffer to overflow, a memory copy operation with any of these values will exceed the bounds of the data segment, resulting in an invalid memory access and potentially causing the application to crash.
5. Exploitation
This section shows a Proof of Concept (PoC) of how to trigger the vulnerability by sending a command to the Widevine trusted application running in the Secure World. Based on the command structure we have derived by reverse engineering, we can craft the command request to be sent to the trusted application:
req->cmd_id = 0x50001; // drm_save_keys; req->feature_name_len = 1; req->file_name_len = 0xffffffff; req->msg_len = 1; …
The Commmand ID 0x50001 is specified to invoke drm_save_keys(), and file_name_len is set to 0xffffffff so that the sum of total_len + file_name_len overflows producing a small value, bypassing the check and eventually calling memcpy() producing the buffer overflow. When this request is sent to Widevine, it ends up crashing.
<5>widevine: "drm_save_keys: feature_name 0xfff00010, feature_name_len 1, file_name 0xfff00110, file_name_len 4294967295, msg_data 0xfff00210 *** crash ***
The Android log in normal world reports that qseecom_send_cmd has failed with error -22, which means APP_FAULTED:
<4>QSEECOM: qseecom_load_app: App (widevine) does’nt exist, loading apps for first time <4>QSEECOM: qseecom_load_app: App with id 3 (widevine) now loaded <3>QSEECOM: __qseecom_send_cmd: Response result -1 not supported <3>QSEECOM: qseecom_ioctl: failed qseecom_send_cmd: -22 <4>QSEECOM: qseecom_unload_app: App id 3 now unloaded
The reason it crashes is because the large memory copy ends up writing to unmapped memory due to exceeding the data segment.
Related news
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys prefix_len+feature_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys prefix_len+feature_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys prefix_len+feature_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys prefix_len+feature_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagParseAndStoreData integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_verify_keys total_len+file_name_len integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 7.1.1 has a PRDiagVerifyProvisioning integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trusted Application (TA) 5.0.0 through 5.1.1 has a drm_save_keys integer overflow and resultant buffer overflow.
Widevine Trustlet versions 5.x, 6.x, and 7.x suffer from a buffer overflow vulnerability in PRDiagParseAndStoreData at 0x5cc8.
Widevine Trustlet versions 5.x, 6.x, and 7.x suffer from a buffer overflow vulnerability in PRDiagVerifyProvisioning at 0x5f90.
Widevine Trustlet versions 5.x, 6.x, and 7.x suffer from a buffer overflow vulnerability in PRDiagVerifyProvisioning at 0x5f90.
Widevine Trustlet versions 5.x, 6.x, and 7.x suffer from a buffer overflow vulnerability in PRDiagVerifyProvisioning at 0x5f90.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_verify_keys at 0x7370.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_verify_keys at 0x7370.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_verify_keys at 0x7370.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_verify_keys at 0x730c.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_verify_keys at 0x730c.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_verify_keys at 0x730c.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_save_keys at 0x6a18.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_save_keys at 0x6a18.
Widevine Trustlet versions 5.x suffer from a buffer overflow vulnerability in drm_save_keys at 0x6a18.
Widevine Trustlet versions 5.x suffer from a drm_save_keys related buffer overflow.
Widevine Trustlet versions 5.x suffer from a drm_save_keys related buffer overflow.
Widevine Trustlet versions 5.x suffer from a drm_save_keys related buffer overflow.
The Widevine QSEE TrustZone application in Android 5.x before 5.1.1 LMY49F and 6.0 before 2016-01-01 allows attackers to gain privileges via a crafted application that leverages QSEECOM access, aka internal bug 24441554.
The Widevine QSEE TrustZone application in Android 5.x before 5.1.1 LMY49F and 6.0 before 2016-01-01 allows attackers to gain privileges via a crafted application that leverages QSEECOM access, aka internal bug 24441554.