二进制漏洞分析-32.华为TrustZone CHINADRM_COMMON_TA漏洞
2024-1-3 07:3:6 Author: 安全狗的自我修养(查看原文) 阅读量:9 收藏

华为TrustZone CHINADRM_COMMON_TA漏洞

此通报包含有关以下漏洞的信息:

  • CVE-2021-40052 漏洞-2021-40052 CencDecrypt 中的目标大小错误memcpy_s

  • HWPSIRT-2021-27669 访问全局变量时缺少锁定

  • HWPSIRT-2021-11381 初始化前打开会话

  • HWPSIRT-2021-11309 会话 ID 是指针

我们发现 3 个影响华为CHINADRM_COMMON_TA的漏洞,这些漏洞可导致以 S-EL0 身份执行的可信应用程序遭到入侵:

  • 访问全局变量时缺乏锁定,导致双重释放和释放后使用问题

  • 在初始化之前可以打开会话,从而导致空指针取消引用

  • 会话 ID 是指针,导致堆指针信息泄露

我们还发现了一个影响华为CHINADRM_COMMON_TA可信应用程序的其他错误:

  • 中的目标大小错误,导致潜在的 ION 缓冲区溢出memcpy_sCencDecrypt

访问全局变量时缺少锁定

正如加载 trustlet 时在日志中显示的那样,它是多会话。因此,在访问或修改全局变量时必须格外小心。不幸的是,这个 trustlet 没有做任何形式的锁定,所以出现了许多竞争条件问题。

[GTask] TA name: CHINADRM_COMMON_TA, UUID: 95b9ad1e, ELF: 361867, stack: 300000, heap: 1179648, multi session: True, keepalive: False, singleInstance: True

如下面的代码片段所示,访问会话列表时不会进行锁定。

int g_sessions_count;      /* in the BSS */
list_head g_sessions_list; /* in the BSS */

int CDRMC_FindSession(container_t *container, session_t **session_p) {
// ...
if (g_sessions_count && container) {
if (list_contains(&container->list, &g_sessions_list)) {
*session_p = container->session;
return 0;
} else { /* ... */ }
} else {
// ...
return -1;
}
// ...
}

因此,可能会出现两个内核位于同一指令窗口中的争用条件,从而导致会话被释放两次。CDRMC_CloseSession

注意:也可以触发释放后使用,让一个内核使用会话(读取或写入会话),而另一个内核释放会话。

int CDRMC_CloseSession(container_t *container) {
// ...
if (CDRMC_FindSession(container, &session)) { /* ... */ }
/* --- start of the race window --- */
if (container->session) {
LicenseExtractInfoCleanup(&container->session->inner);
CDRMR_SecureMemory_Free(container->session);
container->session = NULL;
}
/* --- end of the race window --- */
list_del(&container->list);
CDRMR_SecureMemory_Free(container);
--g_sessions_count;
// ...
}

触发此双重释放的概念证明会导致以下崩溃:

[HM] [ERROR][228]unmap errno = 22
[HM] ERROR: free: __munmap return code= -1
[HM] ERROR: free: double free
[HM] Dump SPI notification entries:
[HM] ----------
[HM] Stats: SHADOW.tx=0 SHADOW.rx=0 WAKEUP.tx=467 WAKEUP.rx=467
[HM] Stats: SET_AFFINITY.tx=0 SET_AFFINITY.rx=0
[HM] Dump current threads:
[HM] ---------
[HM] CPU0: name=/teesmcmgr.elf
[HM] ctx_map[ta=0/0 ca=0/0 target=0/0 exit=0/0]
...

这种缺乏锁定是所有全局变量所共有的。例如,也可以通过 、、 各种证书缓存等而不是会话列表来利用它。g_cipherHandleg_cencCipherHandle

初始化前打开会话

全局会话列表在函数(命令 ID #1)中初始化。如果未显式调用此命令,则列表将处于未初始化状态。CDRMC_Initialize

int g_sessions_count;      /* in the BSS */
list_head g_sessions_list; /* in the BSS */

int CDRMC_Initialize() {
// ...
INIT_LIST_HEAD(&g_sessions_list);
g_sessions_count = 0;
// ...
}

顾名思义,该函数可用于打开会话。它首先调用以确保存储在中的值还不是有效的会话。如果找不到会话或列表为空(即 ),此函数将返回 -1。由于错误路径仅在返回 0 时才被采用,因此即使列表未初始化,也会继续执行。因此,新分配的会话容器的指针将为 NULL 并递增。这在以后可能会导致 null 指针取消引用。CDRMC_OpenSessionCDRMC_FindSessioncontainer_pg_sessions_count == 0CDRMC_FindSessionCDRMC_OpenSessionnextg_sessions_count

int CDRMC_OpenSession(container_t **container_p) {
// ...
if (!CDRMC_FindSession(*container_p, &session)) {
/* ...error... */
}
session = CDRMR_SecureMemory_Malloc(0x2CA8);
container = CDRMR_SecureMemory_Malloc(0xC);
memset_s(session, 0x2CA8, 0, 0x2CA8);
memset_s(container, 0xC, 0, 0xC);
// ...
session->container = container;
container->session = session;
list_add(&container->list, &g_sessions_list);
++g_sessions_count;
*container_p = container;
// ...
}

例如,可以使用函数中的调用(命令 ID #0x29)触发 null 指针取消引用。CDRMC_FindSessionCDRMS_SetPolicy

int CDRMS_SetPolicy(uint32_t paramTypes, TEE_Param params[4]) {
// ...
container_t *container = params[3].memref.buffer;
CDRMC_FindSession(container, &session);
// ...
}

触发此空指针取消引用的概念证明会导致以下崩溃:

[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1e00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x0, fault_code: 0x92000006
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[CHINADRM_COMMON] tid=40 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=7849 prefer-ca=7849
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <CDRMC_FindSession+0x3c/0xdc>
[HM] <CDRMS_SetPolicy>+0xd0/0x1fc
[HM] <CDRMS_SetPolicy>+0xd0/0x1fc
[HM] <TA_InvokeCommandEntryPoint>+0x31c/0x1358
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END

会话 ID 是指针

CA 用来引用会话的会话 ID 是指向结构的堆分配实例的指针。此结构在 中分配,指针在第一个值的第一个值中返回给 CA。CDRMC_OpenSessionTEE_Param

TEE_Result TA_InvokeCommandEntryPoint(
void *sessionContext,
uint32_t commandID,
uint32_t paramTypes,
TEE_Param params[4])
{
switch (commandID) {
case 0x20u:
// ...checking of the paramTypes...
container_t *container = NULL;
retval = CDRMC_OpenSession(&container);
params->value.a = container;
params->value.b = retval;
break;
// ...
}
}

在运行第一个概念验证代码时,我们确实可以观察到返回给 CA 的指针:

Session = 1014db0 (retval = 0)

此信息泄漏可能会派上用场,例如在利用会话列表中的 UAF 时。

目标大小错误memcpy_sCencDecrypt

该函数包含多个调用。其中一些具有不正确的目标大小参数。例如,在上面的代码片段中显示的不正确情况下,目标大小应考虑到值将被复制到 。CencDecryptmemcpy_s*decrypt->outbuf_len_p - offsetoffsetdecrypt->outbuf

int CencDecrypt(asym_decrypt_t *decrypt, int algorithm) {
// CORRECT memcpy_s arguments
if (memcpy_s(
&decrypt->outbuf[offset],
*decrypt->outbuf_len_p - offset,
&decrypt->inbuf[offset],
params_->subSamples[idx].sample_dword_0)) {
tee_print(0, "%s %d:copy clear Header data failed\n ", "[error]", 0x50B);
// ...
}
// ...
// INCORRECT memcpy_s arguments
if (memcpy_s(
&decrypt->outbuf[offset],
*decrypt->outbuf_len_p, // <-- the destination size is incorrect
&decrypt->inbuf[offset],
drmInfo_dword_8_times_0x10)) {
tee_print(0, "%s %d:copy payload pattern clear data failed\n ", "[error]", 0x40A);
// ...
}
// ...
}

我们没有尝试触发此错误,但它可能导致映射的 ION 缓冲区中的缓冲区溢出。

受影响的设备

我们验证了这些漏洞是否影响了以下设备:

  • 麒麟990:P40 专业版 (ELS)

请注意,其他型号可能已受到影响。

补丁

名字严厉CVE漏洞补丁
访问全局变量时缺少锁定不适用固定
初始化前打开会话不适用固定
会话 ID 是指针不适用固定
目标大小错误memcpy_sCencDecryptCVE-2021-40052 漏洞-2021-400522022 年 8 月

时间线

  • 2021年12月09日 - 向华为PSIRT发送漏洞报告。

  • 2022年1月12日 - 华为PSIRT确认该漏洞报告。

  • 2022年8月1日 - 华为PSIRT表示,此问题已在2022年8月更新中修复。

  • 从 2022 年 11 月 30 日至 2023 年 7 月 19 日 - 我们定期交换有关公告发布的信息。

  • ()

  • windows

  • windows()

  • USB()

  • ()

  • ios

  • windbg

  • ()


文章来源: http://mp.weixin.qq.com/s?__biz=MzkwOTE5MDY5NA==&mid=2247490977&idx=1&sn=024ac927d4e219701aa3c7cfe5918882&chksm=c03cf8c5dc155f3c202344ab9869c5c462248ece599a023c404734fb7bc6500990371a0e13ec&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh