二进制漏洞分析-28.华为TrustZone HW_KEYMASTER漏洞
2023-12-23 20:26:30 Author: 安全狗的自我修养(查看原文) 阅读量:25 收藏

  •  

  • -5.(SMC MNTN OOB 访)

  • -10.TrustZone TEE_SERVICE_VOICE_REC

  • -19.TrustZone TCIS

  • -21.TrustZone TALoader

  • -22.TrustZone TA_uDFingerPrint

  • -23.TrustZone TA_SensorInfo

  • -24.TrustZone TA_HuaweiWallet

  • -25.TrustZone TA_SignTool OOB Read

  • -26.TrustZone IfaaKey_TA

  • 二进制漏洞分析-27.华为TrustZone Ifaa漏洞

华为TrustZone HW_KEYMASTER漏洞

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

  • CVE-2021-40017 漏洞 将任意数据写入 sec_storage_data/PKI/

  • CVE-2021-40040 漏洞 写入在 generate_keyblob 中设置的受控参数

  • CVE-2021-46887 漏洞 ber_pop_front中的整数溢出

  • HWPSIRT-2021-26563 cmd_verify_key中的堆栈地址泄漏

  • HWPSIRT-2021-07329 ber_init中的整数溢出

  • HWPSIRT-2021-63468 verify_root_cert中的逻辑问题

  • HWPSIRT-2021-73188 get_soter_cpuid中的堆栈缓冲区溢出

  • HWPSIRT-2021-53224 get_soter_cpuid中的 OOB 访问

我们发现 3 个影响华为可信应用程序的漏洞,这些漏洞可用于在 S-EL0 上实现代码执行:HW_KEYMASTER

  • 写入任意数据导致任意读取内存(甚至可能是任意写入);sec_storage_data/PKI/

  • 将受控参数写入任意内存地址(名称是我们自己的);generate_keyblob

  • 整数溢出(名称是我们自己的),导致对任意内存地址的 OOB 读取访问。ber_pop_front

我们还发现了影响华为可信应用程序的另外 5 个错误:HW_KEYMASTER

  • 堆栈地址泄漏(名称是我们自己的);cmd_verify_key

  • 一个整数溢出(名称是我们自己的);ber_init

  • (名称是我们自己的)中的逻辑问题;verify_root_cert

  • 堆栈缓冲区溢出(名称是我们自己的);get_soter_cpuid

  • 一个 OOB 访问权限(名称是我们自己的)。get_soter_cpuid

将任意数据写入sec_storage_data/PKI/

0x2C0F8 函数和 0x2A1E8 函数可用于将任意数据写入 SFS 文件夹中的任何文件。由于用户可以指定 key、nonce 和 aad,因此他们可以发送输入和标记,从而生成他们选择的纯文本。因此,文件名和文件数据是完全可控的。cmd_unwrapunwrap_asset_data_and_write_it_to_filesec_storage_data/PKI/

int cmd_unwrap(int paramTypes, TEE_Param params[4]) {
// ...
// wrap_key_type, associated_data, account_uid and assetstore_base_pwd
// are extracted from the params set contained in params[0]
params_from_key_params = get_params_from_key_params(
params[0].memref.buffer,
&wrap_key_type,
&associated_data,
&account_uid,
&assetstore_base_pwd);
// ...
// fst_alias and snd_alias (2 strings), and wrap_key_type (integer)
// are extracted as TLVs from params[1]
key_aliases = get_key_aliases(
params[1].memref.buffer,
params[1].memref.size,
&fst_alias,
&snd_alias,
wrap_key_type);
// ...
// we can specify wrap_key_type == 1
switch (wrap_key_type) {
case 1:
// if fst_alias is the alias of an AES key, its keymaterial
// will be retrieved from the SFS and put into key_param
get_aes_keymaterial_from_alias(&key_param, fst_alias.buf, fst_alias.len);
// ...
// a buffer of size 0x1000 is allocated to contain the plaintext
decrypt_data.buf = TEE_Malloc(0x1000, 0);
decrypt_data.len = 0x1000;
// ...
// the ciphertext contained in params[2] (as a TLV, alongside the nonce
// and tag) is decrypted using the aforementioned AES key, using the
// AES-256-CCM crypto algorithm (the AAD is derived from associated_data)
unwrap_asset_data_and_aes_decrypt(
key_param.buf,
key_param.len,
uid.buf,
uid.len,
&params[2].memref.buffer,
&params[2].memref.size,
&decrypt_data);
// ...
// unwrap_asset_data_and_write_it_to_file is called with the
// user-controlled plaintext and snd_alias
unwrap_asset_data_and_write_it_to_file(
decrypt_data.buf,
decrypt_data.len,
snd_alias.buf,
snd_alias.len,
&params[3]);
// ...
}
// ...
}

int unwrap_asset_data_and_write_it_to_file(
int *decrypt_buf,
int decrypt_len,
int snd_alias_buf,
int snd_alias_len,
TEE_Param *param3) {
// ...
tlv_buffer = decrypt_buf;
tlv_val_p = &tlv_val;
tlv_val.buf = 0;
tlv_val.len = 0;
tlv_size = decrypt_len;
expected_tags[0] = 2;
// ...
// tlv_val is extracted as an TLV value from the plaintext data
parse_unwrap_asset_data_tlv(&expected_tags, 1, &tlv_buffer, &tlv_size, &tlv_val_p);
// ...
// tlv_val is written to the SFS to the sec_storage_data/PKI/<snd_alias> file
write_data_to_file_by_alias(snd_alias_buf, snd_alias_len, tlv_val.buf, tlv_val.len);
// ...
}

此漏洞具有安全隐患,因为该文件夹包含 Keymaster 使用的各种类型的文件(特别是 keyblob)。伪造 keyblob 的内容可能会导致任意读取,也可能导致任意写入,正如我们将在利用部分看到的那样。sec_storage_data/PKI/

写入 中设置的受控参数generate_keyblob

0xB0CC 处的函数应为 memref,因为它将使用刚刚生成的 keyblob 的参数集填充它(使用 0xA1C8 处的函数)。但是,下面报告了一个代码路径,该路径从 a 开始并允许到达 a 值而不是 memref。这意味着参数集数据将被写入任意地址。此外,由于参数集来自 ,写入的数据也部分由用户控制。generate_keyblobparams[3]resort_key_characteristicscmd_begingenerate_keyblobparams[1]params[1]

易受攻击的代码路径如下:

  • cmd_begin在0xC540

  • get_key_blob在0xBE60

  • process_begin_for_keychain_new在0xBCC0

  • generate_symmetric_keymaterial_special在0xBA98

  • generate_keyblob在0xB0CC

  • resort_key_characteristics在0xA1C8

int cmd_begin(unsigned int paramTypes, TEE_Param params[4]) {
// ...
get_key_blob(params, params_enforced, &key_blob, &vendor_type);
// ...
}

int get_key_blob(
TEE_Param *params,
unsigned int *params_enforced,
keyblob_t **keyblob_p,
int *vendor_type_p) {
// ...
return process_begin_for_keychain_new(v10, v13, v12, v11);
// ...
}

int process_begin_for_keychain_new(
int access_limit,
TEE_Param *params,
unsigned int *params_enforced,
keyblob_t **keyblob_p) {
// ...
generate_symmetric_keymaterial_special(key_data, 0x100u, &derive_factor, params, keyblob_p);
// ...
}

int generate_symmetric_keymaterial_special(
char *key_data,
unsigned int key_size,
key_param_t *derive_factor,
TEE_Param *params,
keyblob_t **keyblob_p) {
// ...
generate_keyblob(&derived_key, 0, params, 1, keyblob_p);
// ...
}

int generate_keyblob(
key_param_t *derived_key,
int a2,
TEE_Param *params,
int use_second_param,
keyblob_t **keyblob_p) {
// ...
if (use_second_param == 1)
params_set = params[1].memref.buffer;
else
params_set = params[0].memref.buffer;
// ...
keyblob = TEE_Malloc(0x1000u, 0);
keyblob->magic = 'HIKM';
keyblob->version = 0x12C;
memcpy_s(keyblob->blob, 0xFA0, derived_key->buf, derived_key->len);
keyblob->key_len = derived_key->len;
keyblob->key_off = 0x60;
// ...
hw_params_off = (derived_key->len + 0x63) & 0xFFFFFFFC;
hw_params_count = *(uint32_t *)params_set;
*(uint32_t *)(keyblob + hw_params_off) = hw_params_count;
memcpy_s(keyblob + hw_params_off + 4, 0xFFC - hw_params_off, params_set + 1, 0x10 * hw_params_count);
keyblob->hw_params_off = hw_params_off;
// ...
// copying of the sw_params in a similar fashion
// ...
// copying of the out-of-line params set data in a similar fashion
// ...
sort_params_set = params[3].memref.buffer;
if (!sort_params_set) // ...
sort_params_set_size = params[3].memref.size;
if (!sort_params_set_size) // ...
total_size = extra_end_offset - keyblob_->hw_params_off;
if (sort_params_set_size < total_size) // ...
resort_key_characteristics(sort_params_set, hw_params_ptr, total_size);
// ...
}

我们在本报告的利用部分演示了这种任意写入。

整数溢出ber_pop_front

int ber_pop_front(ber_t *out_ber, ber_t *in_ber, int expected_type, int expected_class, int allowed_flag) {
// ...
read_ptr = in_ber->read_ptr;
// ...
tag = ber_read_byte(in_ber);
// ...
first_length = ber_read_byte(in_ber);
// ...
length = first_length;
if (first_length & 0x80) {
length = 0;
for (int i = 0; i < first_length & 0x7F; ++i)
length = ber_read_byte(in_ber) | (length << 8);
}
// ...
new_end = in_ber->read_ptr + length;
if (new_end <= in_ber->buf_end) {
in_ber->read_ptr = new_end;
out_ber->read_ptr = read_ptr;
out_ber->buf_end = new_end;
} else {
// ...
}
// ...
}

0x1D54处的函数包含加法上的整数溢出。通过为 指定负值,可以在缓冲区开始之前进行点。然后,下次调用此指针来读取 BER 编码值时,将导致 OOB 读取访问。ber_pop_frontin_ber->read_ptr + lengthlengthnew_endber_pop_front

我们通过概念验证触发了此错误,并在以下位置获得了以下崩溃:0x2ebefec9 = 0x7000400a - 0x41414141

[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 2200000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x2ebefec9, fault_code: 0x92000006
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[HW_KEYMASTER] 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=9358 prefer-ca=9358
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <?>+0x0/0x0
[HM] <TA_InvokeCommandEntryPoint>+0x64/0xd8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
[HM] [TRACE][1212]pid=51 exit_status=130

堆栈地址泄漏cmd_verify_key

0x39E80处的函数包含对函数的调用,该函数将打印堆栈变量的地址。可以使用 检索此日志消息。我们无法触发位于错误路径中的调用。cmd_verify_keySLoglogcat

.text:0003A3F4  LDR  R1, =(aError - 0x3A408) ; "[Error]"
.text:0003A3F8 SUB R3, R11, #-a2
.text:0003A3FC LDR R0, =(aSCurrentCertIt - 0x3A40C) ; "%s: current cert iterator[%u] > count[%"...
.text:0003A400 ADD R1, PC, R1 ; "[Error]"
.text:0003A404 ADD R0, PC, R0 ; "%s: current cert iterator[%u] > count[%"...
.text:0003A408 BL SLog

整数溢出ber_init

0x1FB8 处的函数包含加法上的整数溢出。我们没有找到触发此错误的方法,因为大小来自其中一个,并且它们的大小在内核端限制为 1 MB。ber_initbuf + sizeTEE_Params

ber_t *ber_init(ber_t *ber, uint8_t *buf, uint32_t size, ber_state_t *state) {
state->error = 0;
state->error_ptr = 0;
ber->read_ptr = buf;
ber->buf_end = buf + size;
ber->state = state;
return ber;
}

int cmd_sop_decrypt(unsigned int paramTypes, TEE_Param params[4]) {
// ...
ibuf1_addr = params[1].memref.buffer;
if (!ibuf1_addr) // ...
// ...
ibuf1_size = params[1].memref.size;
if (!buf1_size) // ...
// ...
ber_init(&ber, ibuf1_addr, ibuf1_size, &state);
// ...
}

中的逻辑问题verify_root_cert

0x34700处的函数用于验证当前安装的根证书(保存在弹性文件服务上)是否与用户提供的证书链中的根证书相同。比较存在逻辑问题,因为只有当大小不同且内容不同(而不是 OR)时才会出现错误情况。我们没有评估此错误的安全影响。verify_root_cert

unsigned int verify_root_cert(cert_entry_t *certs) {
// ...
cert_entry_t root_certs[3];
memset(root_certs, 0, sizeof(root_certs));

for (int i = 0; i < 3; ++i) {
cert_entry = get_cert_entry(1, 1, i, &root_certs[i]);
// ...
}

if (root_certs[2].len != certs[2].len
&& TEE_MemCompare(root_certs[2].buf, certs[2].buf, root_certs[2].len)) {
ret = -1;
SLog("%s: verifyRootCert fail\n\n", "[Error]");
}

free_certs(root_certs, 3);
return ret;
}

堆栈缓冲区溢出get_soter_cpuid

0x18510 处的函数可能会溢出它作为参数给出的缓冲区。如果 (从用户可以设置的证书中提取) 的大小等于缓冲区的大小,则大小为 9 的随机十六进制字符串将被写入缓冲区的边界之外。get_soter_cpuidcommon_namehexbuf

此函数通过 0x18794 处的函数在 3 个位置调用:get_soter_cntr_or_cpuid

  • 在 0x18C1C 的功能中build_json_for_attestation

  • 在 0x18DCC 的函数中build_json_message_to_sign

  • 在函数中0x19BF8build_soter_json_AK

在每种情况下,都会在堆栈上分配溢出的缓冲区(大小为 0x80)。我们没有尝试触发此错误。

int build_json_for_attestation(int a1, int a2, int a3, int a4) {
// ...
char s[128];
// ...
memset(out_buf, 0, sizeof(out_buf));
out_buf_len = 0x80;
get_soter_cntr_or_cpuid(0, out_buf, &out_buf_len);
// ...
}

int get_soter_cntr_or_cpuid(int a1, char *out_buf, uint32_t *out_buf_len_p) {
get_soter_cpuid(out_buf, out_buf_len_p);
}

int get_soter_cpuid(char *out_buf, uint32_t *out_buf_len_p) {
char hexbuf[12];
// ...
cert_entry = get_cert_entry(1, 1, 0, &cert);
// ...
get_cert_dn_component_maybe(&component, 5u, cert.buf + 4, cert.len - 4);

while (component[0] != 6 || component[1] != 3 || TEE_MemCompare(component + 2, &g_common_name_oid, 3))
++component;

cpuid = component[5];
common_name_len = component[6];
common_name = component + 7;
out_buf_len = *out_buf_len_p;
component += 7;
if (out_buf_len < common_name_len) {
SLog("%s: out_buf_len:%u is less than cert_entry'CN:%d\n", "[Error]", out_buf_len, common_name_len);
goto LABEL_3;
}
TEE_MemMove(out_buf, common_name, common_name_len);
*out_buf_len_p = common_name_len;
// ...

rndbuf = TEE_Malloc(4, 0);
TEE_GenerateRandom(rndbuf, 4);
hexbuf[0] = 0x2D;
to_hex_string(rndbuf, 4, &hexbuf[1], 8u);
TEE_MemMove(&out_buf[*out_buf_len_p], hexbuf, 9u);
*out_buf_len_p += 9;
// ...
}

OOB 访问get_soter_cpuid

如果证书不包含公用名,则 0x18510 处的函数也可以触发 OOB 访问。只要找不到公用名 OID,while 循环就会无限期地继续递增。get_soter_cpuidcomponentcomponent

int get_soter_cpuid(char *out_buf, uint32_t *out_buf_len_p) {
char hexbuf[12];
// ...
cert_entry = get_cert_entry(1, 1, 0, &cert);
// ...
get_cert_dn_component_maybe(&component, 5u, cert.buf + 4, cert.len - 4);

while (component[0] != 6 || component[1] != 3 || TEE_MemCompare(component + 2, &g_common_name_oid, 3))
++component;
// ...
}

开发

我们将利用我们提到的两个漏洞来证明我们可以从这些漏洞中获得任意读/写。有问题的漏洞是写入任意数据以及写入 中设置的受控参数。sec_storage_data/PKI/generate_keyblob

我们的设备设置

我们开发漏洞利用的设备是运行固件更新的P40 Pro。ELS-LGRP4-OVS_11.0.0.223

trustlet 二进制 MD5 校验和如下:

HWELS:/ # md5sum /vendor/bin/86310d18-5659-47c9-b212-841a3ca4f814.sec
e5b15daf991407ee3c440b98b7e5cb23 /vendor/bin/86310d18-5659-47c9-b212-841a3ca4f814.sec

华为TEE OS iTrustee实现了白名单机制,只允许特定的客户端应用(原生二进制文件或APK)与可信应用通信。

在我们的例子中,HW_KEYMASTER TA 只能由以下 CA 调用:

  • /system/bin/keystore(UID 1017)

  • /system/bin/vold(UID 0)

  • /vendor/bin/atcmdserver(UID 0)

  • /vendor/bin/hw_cert_service(UID 0)

  • /vendor/bin/hw/[email protected](UID 1000)

  • /system/bin/tee_test_ut(UID 0)

  • com.huawei.systemserver(APK)

  • com.huawei.hwonlineprovisionservice(APK)

身份验证机制分 3 个部分实现:

  • 实现 TEE 客户端 API 的守护进程检查哪个原生二进制文件/APK 正在与它通信,并将该信息发送到内核驱动程序;teecd

  • 内核驱动程序确保它正在与 通信,并将其接收到的信息转发给 TEE OS;teecd

  • TEE OS 验证客户端应用程序是否在 TA 的白名单中。

由于我们不想费心在这些二进制文件之一中注入代码,因此我们选择通过修补内核驱动程序来规避身份验证,以添加模拟任何原生二进制文件/APK 的功能。

任意读取

为了触发向SFS写入任意数据,我们首先使用命令(ID 0x10003)导入全零AES密钥(带有别名)。然后,我们通过使用 AES-256-CCM 加密文件数据来准备文件数据,并使用全零密钥、全零 IV 和 SHA256 哈希作为关联数据。最后,我们使用别名、全零 IV、关联数据以及我们之前计算的加密文件数据和标记来调用命令 (ID 0x1001)。keycmd_import_aes_key86310d18-5659-47c9-b212-841a3ca4f814\x00...16 times...\x00cmd_unwrapkey\x00...16 times...\x00

int cmd_get(unsigned int paramTypes, TEE_Param params[4]) {
// ...
ret = get_keyblob_from_alias(
&keyblob,
&keyblob_size,
params[0].memref.buffer,
params[0].memref.size,
params[2].value.a);
// ...
if (keyblob->magic == 0x534554
&& keyblob->version <= 0x12C
&& keyblob->keyblob_total_size == keyblob_size) {
memcpy_s(
params[1].memref.buffer,
params[1].memref.size,
keyblob + keyblob->key_off,
keyblob->key_len);
// ...
params[1].memref.size = keyblob->key_len;
}
// ...
}

为了触发相对读取,我们将“假”keyblob 写入文件,并使用相同的文件名调用命令 (ID 8)。此命令将读取文件并将其内容放入 .由于我们可以控制 keyblob 文件的全部内容,因此我们可以通过检查并让命令调用 . 将从用户控制的相对于对象的偏移量复制到,并具有用户控制的大小。由于 keyblob 是堆分配的,因此我们可以泄漏堆的内容。sec_storage_data/PKI/blobcmd_getblobkeyblobmemcpy_smemcpy_sparams[1]keyblob

以下是堆内容的摘录:

...
X + 0x80 : 58 f0 c0 03 d0 89 fe 00 67 70 64 2e 74 61 2e 61 X.......gpd.ta.a
X + 0x90 : 70 70 49 44 00 18 0d 31 86 59 56 c9 47 b2 12 84 ppID...1.YV.G...
X + 0xa0 : 1a 3c a4 f8 14 00 00 00 41 00 00 00 41 00 00 00 .<......A...A...
X + 0xb0 : d8 89 fe 00 02 00 00 00 01 00 00 00 04 00 00 00 ................
X + 0xc0 : 90 89 fe 00 10 8a fe 00 67 70 64 2e 74 61 2e 73 ........gpd.ta.s
X + 0xd0 : 69 6e 67 6c 65 49 6e 73 74 61 6e 63 65 00 25 73 ingleInstance.%s
X + 0xe0 : 20 25 00 00 00 00 00 00 41 00 00 00 41 00 00 00 %......A...A...
X + 0xf0 : 18 8a fe 00 02 00 00 00 01 00 00 00 04 00 00 00 ................
X + 0x100: d0 89 fe 00 50 8a fe 00 67 70 64 2e 74 61 2e 6d ....P...gpd.ta.m
X + 0x110: 75 6c 74 69 53 65 73 73 69 6f 6e 00 25 73 20 25 ultiSession.%s %
X + 0x120: 00 00 00 00 00 00 00 00 41 00 00 00 41 00 00 00 ........A...A...
X + 0x130: 58 8a fe 00 02 00 00 00 01 00 00 00 04 00 00 00 X...............
...

为了能够从任意地址读取数据,我们需要泄漏 .在转储堆时,我们注意到字符串周围有两个指针(一个指针在,一个指针在),具有相同的值(在上面的转储中)。多亏了这些指针,我们可以推断出位于它们之间的对象的地址(在上面的转储中),从而推断出我们的对象的地址。keyblobgpd.ta.appIDnextX + 0x84prevX + 0x100d0 89 fe 00X + 0xc0keyblob

然后,我们使用任意读取和 TALoader 信息泄漏来查找 trustlet 的基址。最后,我们使用此地址转储 trustlet 的内存,作为本演示的最后一步。

任意写入

要触发对内存的任意写入,我们首先使用 调用命令 (ID 0x30001)。这将初始化下一步所需的用户密钥。cmd_on_user_eventevent_type == 2

然后,我们使用以下参数集值调用命令 (ID 3):cmd_beginparams[1]

  • KM_TAG_VENDOR_TYPE: 1

  • KM_TAG_ASSETSTORE_ACCESSLIMITATION: 2

  • KM_TAG_PURPOSE: 0x41414141

  • KM_TAG_DERIVE_FACTOR:\x00...16 times...\x00

  • 0x90015FB9:\x00\x00\x00\x00

这些值允许访问漏洞详细信息中显示的代码路径。我们指定要写入的地址和大小。复制这些值时,将检查我们提供的大小,并且需要确保它足够大以包含参数集缓冲区中的值。最后,为了表明我们控制了一些正在写入的数据,我们选择设置一个自定义参数值。params[3].value_aparams[3].value_bKM_TAG_PURPOSE

请注意,如果需要控制超过 1/2/4/8 个连续字节的写入数据,我们还可以使用类型为 的可复制标签,例如包含行外数据的 0x900002C3、0x900002C4 或 0x900003EA。KM_BYTES

您可以在下面找到我们设备上运行的漏洞利用的输出:

adb wait-for-device shell su root sh -c "\"LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/poc\""
object is at 10c0910
ta_base_addr = 39ae000
TA memory dump:
0x039ae000: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 .ELF............
0x039ae010: 03 00 28 00 01 00 00 00 0c 1d 00 00 34 00 00 00 ..(.........4...
0x039ae020: dc 81 0b 00 00 02 00 05 34 00 20 00 05 00 28 00 ........4. ...(.
0x039ae030: 11 00 10 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
...
Writing a params set to an arbitrary address...
Reading the params set that was just written...
0x70000800: 05 00 00 00 01 00 00 20 00 00 00 00 41 41 41 41 ....... ....AAAA
0x70000810: 00 00 00 00 be 02 00 10 2c f8 a9 03 00 00 00 00 ........,.......
0x70000820: 04 fa a9 03 c1 02 00 30 00 00 00 00 00 00 00 00 .......0........
0x70000830: 00 00 00 00 c2 02 00 30 00 00 00 00 00 00 00 00 .......0........
...

获取代码执行

虽然它不包含在漏洞利用中,但可以通过替换函数指针/覆盖返回地址和链接 ROP 小工具来执行代码。有很多小工具可供选择,因为共享库(、、等)映射在 trustlet 的地址空间中。libc_shared_a32.solibtee_shared_a32.solibvendor_shared_a32.so

例如,这可用于进行任意系统调用,并可能进一步提升权限。

受影响的设备

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

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

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

补丁

名字严厉CVE漏洞补丁
将任意数据写入sec_storage_data/PKI/危急CVE-2021-40017 漏洞2022 年 <> 月
写入 中设置的受控参数generate_keyblob危急CVE-2021-40040 漏洞2022 年 <> 月
整数溢出ber_pop_frontCVE-2021-46887 漏洞2023 年 <> 月
堆栈地址泄漏cmd_verify_key不适用固定
整数溢出ber_init不适用固定
中的逻辑问题verify_root_cert不适用固定
堆栈缓冲区溢出get_soter_cpuid不适用固定
OOB 访问get_soter_cpuid不适用固定

时间线

  • 24年2021月<>日,华为PSIRT收到漏洞报告。

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

  • 01年2023月2022日 - 华为PSIRT表示,这些问题已在2023年<>月和<>年<>月的更新中修复。

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

  • 21年2023月<>日 - 华为PSIRT通知华为PSIRT,部分漏洞未修复。

  • 03年2023月2023日 - 华为PSIRT回复,将在<>年<>月更新中修复。

  • ()

  • windows

  • windows()

  • USB()

  • ()

  • ios

  • windbg

  • ()


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