676b847a9f98ba265891bc041b6b41c0.png

0x00 前言

在第二篇系列文章中,我们将继续通过逆向工程技术来探索TEEGRIS,从而发现并利用其中存在的安全漏洞。

0x01 TA漏洞分析

1.1 Global Platform(GP)接口

正如第一篇文章所述,TA实现了GP接口。其中我们最关注的入口点是,它在每次客户端应用程序(CA)向TA发送命令时执行。

在GP规范中,记录了该函数的原型。

的描述:

TA_InvokeCommandEntryPoint

TA_InvokeCommandEntryPoint

b0996114ed4334b82b38c5b301979226.png

该API允许CA最多指定4个参数。每个参数都有一个关联的参数类型。在这份GP文档中同时还列出了可选的参数类型。

GP参数类型:

6b1abfaa5e5b8b45d6fd7d9f3b451c27.png

假设这里使用了一个参数(因此其类型不是),这里主要涉及到两种类型,分别是和。每种参数类型的值被编码为半字节,合并在一起组成了参数。

是一个union类型,其定义如下。

Union定义:

TEE_PARAM_TYPE_NONE

value

memref

paramTypes

TEE_Param

TEE_Param

8108eb01e731fba309938e467d14bd08.png

根据参数是类型还是类型,其填充内容也有所不同:

(1):成员和被设置为与CA传递的值完全相同的值。

(2):CA将引用传递给其私有内存中的缓冲区。TEE OS将在TA的地址空间中映射相同的内存,并相应地填充union的和成员。具体而言,将指向TA内存空间中保证有效的虚拟地址。这样,TA和CA都会有相同物理内存的视图。

从描述中可以明显看出,检查参数类型这一点至关重要。如果TA期望使用,但CA却传递了一个值,这样则不能保证或指向有效的共享内存位置。这可能会导致类型混乱,其中CA可以完全控制TA认为有效的缓冲区指针及大小。

value

memref

value

a

b

memref

buffer

size

buffer

memref

buffer

a

1.2 在TA中的GP检查

考虑到这个检查的重要性,我们确实有必要验证所有TA是否正确实施了这一检查。出乎意料的是,似乎并不是所有TA都有完善的检查。

TIMA TA参数类型验证:

ba9cd57e8c97b39c49f5f388b8ebe17e.png

TA首先正确检查参数,如果它们并非预期值,则返回错误。这是符合预期的行为,不存在风险。

现在,我们切换到另一个TA,也就是HDCP TA(UUID 00000000-0000-0000-0000-000048444350)。

HDCP TA参数类型验证:

paramTypes

9c2719fcd2251e2f0065f2c3a2c912f7.png

这个TA完全不包含对参数类型的检查。这些参数可以从输入中获取,并直接传递给main函数。这意味着,可以对这个TA进行类型混淆攻击。

假设我们现在可以将输入参数设置为所需的任何值,我们可以尝试找到一种利用该参数的方法。理想情况下,我们希望利用它来实现任意读写,然后在利用它获得对TA的运行时控制。

在分析了TA中实现的所有命令之后,我们发现可以组合使用其中的三个命令,从而获得读写原语。由于GP API没有定义任何标准命令,因此我们不知道在TA中实现命令的确切目的。它们是特定于TA的,并且不同TA中的相同命令值可能具有完全不同的功能。我们的目标命令是FB、FC和CB。

(1)FB命令:

c4ad249edad8dfd4705367b2856935de.png

这个命令从Android应用程序获取输入缓冲区,将其包装到安全对象中(意味着该缓冲区已经使用TA专用密钥进行加密和签名),然后将安全对象返回给应用程序。由于类型混淆漏洞,攻击者可以完全控制输入和输出指针。但是,由于输出内容是不可预测的,因此命令本身不能提供非常强大的原语。

(2)FC命令:

6691c7bc803fbadc642a7c4a4857696d.png

FC命令与FB命令执行相反的操作:它会获取一个安全对象,并将其解包回原始内容。但是,解包的输出不会返回到REE,而是存储在TA内的固定内存位置。

(3)CB命令:

fe4c5d9959d7d7f67f6a434e525af41c.png

最后,CB命令获取包含未包装数据的缓冲区,并将其一部分返回给REE。请注意,由于类型混淆漏洞,目标地址也可以设置为指向TA内部内存。

通常,三个命令组合使用的场景如下:

bd71718de91d83a4e94a04d9ff543dae.png

FB命令接收来自REE的输入,对其进行加密,然后将其返回给REE。REE使用FC命令将其传递给TA,后者将其揭秘并存储在TA内部内存位置中。最后,使用CB命令将缓冲区的一部分返回到REE。最终结果是CB命令的输出是FB命令输入的部分副本。

可以通过指定FB命令的输入指向TA内部内存,并指定CB命令的输出以指向REE内存的方式,实现任意读取。

对FB命令输入进行类型混淆攻击以提取TA内存:

390168010392ecb5359e0380240e4643.png

类似地,还可以通过将FB命令的输入设置为REE内存,并将CB命令的输出设置为TA内存的方式,实现任意写入。

对CB命令输出进行类型混淆攻击以覆盖TA内存:

839d7e923833dfb694d27a7fc526d225.png

现在,我们就可以在HDCP TA中实现任意读写。由于TA被认为是安全的,并且与不受信任的Android OS完全隔离,因此这已经是我们的一大突破。不过,三星实施了漏洞利用缓解措施,所以这里还有两个问题:

(1)由于ASLR,我们不知道TA的确切内存映射位置。

(2)因为我们想利用TA提升特权,获得对整个TEE内存的完整访问权限,所以我们可能也希望获得代码执行。

1.3 绕过ASLR

如上篇文章所说,ASLR的原理是对代码和数据段进行随机化。这个随机的范围是0到32767之间的随机数乘以4096(页大小)。

我们没有找到能够以某种方式泄露信息(例如指针值)的方法,如果能有这样的信息,我们就可以恢复随机偏移量。如果我们仅仅是将上述三个命令组合起来,尝试从随机位置读取,会发生什么情况?实际上,TA将会崩溃,在Android中我们将可以在中看到错误日志。

但是,它不会阻止我们再次尝试与同一个TA进行交互,也不会阻止访问同一个随机地址。这一次,可以看看是否足够幸运,可以命中真实的映射内存。这个过程可以重复多次,直到映射了我们尝试访问的地址。由于可能的随机数只有32k,因此找到真实的随机数并不是那么困难,通常可以在不到一分钟的时间内完成。尽管这样的效率在漏洞利用过程中并不理想,但还是可以接受的。另外,实际上我们碰到有效随机数的机会是大于1/320000的,因为我们已经有了任意读取原语,只需要从映射的二进制文件中查找和读取一页即可。在提取内存的内容后,我们可以将它们与已知的二进制内容进行匹配,以检索实际的随机偏移量。

1.4 实现代码执行

在这个阶段,我们已经有了任意读写权限和ASLR绕过方式。在拥有了如此强大的原语之后,利用它们来获取代码执行就不是一个困难的问题。可能会有几种不同的思路,最终我们决定将其与在TA中发现的另一个栈缓冲区溢出漏洞结合起来。

命令在请求缓冲区中接收某些信息,对传递的参数执行一些验证,然后根据设置的HDCP版本调用函数或。但是,如下图所示,参数验证的过程仅仅是比较两个攻击者提供的值,也就是和。这样一来,攻击者就可以构造请求,确保检查通过。

反编译的函数:

TZ_RepeaterAuth_Send_ReceiverId_List_T()

TZ_RepeaterAuth_Send_ReceiverId_List20_T()

TZ_RepeaterAuth_Send_ReceiverId_List21_T()

request[3]

req_size

TZ_RepeaterAuth_Send_ReceiverId_List_T

cf1f0210e9b0fd56345b982fb6b35dea.png

在下图中跳转到函数,我们可以看到将请求缓冲区的内容复制到一个160字节的数组中,该数组驻留在栈中,大小控制为。这会导致缓冲区存在栈缓冲区溢出。

反编译的函数:

TZ_RepeaterAuth_Send_ReceiverId_List20_T()

5 * request[3]

in

TZ_RepeaterAuth_Send_ReceiverId_List20_T

8c5555f91e49969a7bee0f771c03b4e0.png

这是非常经典的栈缓冲区溢出,我们在其中控制复制的大小和缓冲区内容。最多可以复制1275个字节,这样就有足够的空间来存储Shellcode。但是,TA还使用了栈金丝雀(Stack Canaries)防护,如下图所示,所以漏洞利用就变得困难起来。

反编译的末尾部分:

TZ_RepeaterAuth_Send_ReceiverId_List20_T

20b805aaa02034c0e0fc7560a3faed85.png

由于我们现在有任意读取和ASLR绕过,所以可以轻松读取的值并将其填充到我们的Shellcode中,以便使金丝雀验证通过。

我们尝试将所有步骤结合起来,以证明最终可以控制HDCP TA中的程序计数器(PC)。当栈金丝雀设置为错误的值时,我们在中可以看到如下调试信息:

__stack_chk_guard

dmesg

[38142.232347] SW> [TEEgris:SCrypto] SCrypto 2.4 is in FIPS approved mode[38142.232374] SW> HDCP : TA_CreateEntryPoint[38142.232381] SW> HDCP : TA_OpenSessionEntryPoint[38142.240917] SW> TZ_SET_HDCP_VERSION_T : HDCP 2.0 version is setuped[38142.243372] SW> *** tzsl detected *** Stack smashing[38142.243387] SW> rettadr: 0x286f9c

在读取并正确设置金丝雀后,我们将栈上的返回地址替换为,则会打印如下内容:

0xAAAAAAAA

[37276.997902] SW> [TEEgris:SCrypto] SCrypto 2.4 is in FIPS approved mode[37276.997921] SW> HDCP : TA_CreateEntryPoint[37276.997928] SW> HDCP : TA_OpenSessionEntryPoint[37277.005590] SW> TZ_SET_HDCP_VERSION_T : HDCP 2.0 version is setuped[37277.007939] SW> Samsung Secure OS Release Version 3.1.0.0 (15415496 15403694) built on: 2019-02-14 16:37:50, binary version: 9e91f07b[37277.007952] SW> Th#2528 of Pid=5344 panicked with signal: 5 (SIGTRAP)[37277.007960] SW> Fault addr 0xaaaaaaaa in module N/A

至此,TA漏洞利用的第一部分就告一段落。我们在HDCP TA中获得了任意读取、写入和代码执行。但是,由于XN,我们只能够复用现有的代码,这一点会在下一篇文章中进行更多分析。

0x02 TA防回滚机制

在研究过程中,我们发现三星当时最新的安全补丁公告中包含了如下内容。

三星版本发布公告,涉及HDCP TA参数类型检查:

490a22b0fa166d61802d00b534ddbf7e.png

似乎已经有研究人员将缺失的参数检查报告给三星,并且得到了修复。但是,修复方法真的是正确的吗?让我们看一下新的。

新HDCP TA中的:

TA_InvokeCommandEntryPoint

TA_InvokeCommandEntryPoint

50aa0ebdde8a9c23f352964f47d6cb32.png

该函数似乎对参数类型实施了适当的检查。基于栈的缓冲区溢出漏洞仍然存在,但是如果没有泄露金丝雀的方法,我们就无法对其进行利用。这样一来,我们之前的成果就付之东流了。

但事实并非如此,我们发现,TA只是REE传递给药执行的TEE的代码签名blob。如果REE要求TEE执行旧版本的TA,会发生什么情况?在上篇文章中,我们看到根据TA版本的不同,可以启用防回滚功能。SEC2版本不支持这个功能,而SEC3和SEC4支持。新的HDCP TA标头中指定的版本是什么?我们用十六进制编辑器打开它。

新的TA标头:

看来新的TA版本仍然是SEC2!这意味着,不会有任何防回滚的机制。随后,我们可以进行验证,将手机的固件升级到较新版本,创建修改后的副本,该副本将会在查找TA,而不是。这样一来,我们可以将旧的TA放在中,并让TEE执行旧版本的TA。

实际上,TEEGRIS OS允许加载旧版本的TA,该TA仍然包含可以利用的漏洞。这意味着,即使新版本TA正确修复了参数检查问题,攻击者也可以强制TEE加载旧版本TA,以回到易受攻击的状态。

libteecl.so

/data/local/tmp

/vendor/tee

/data/local/tmp

0x03 总结

在这篇文章中,我们演示了发现并利用HDCP TA中两个漏洞的详细过程,同时还说明了TEE中防回滚机制的重要性。

欢迎大家继续关注下一篇文章,我们将详细分析如何提升特权,并获得对整个TEE内存的完整访问权限。

欢迎登录安全客 -有思想的安全新媒体www.anquanke.com/加入QQ交流群1015601496 获取更多最新资讯

原文链接:https://www.anquanke.com/post/id/237029

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐