Android Drm service堆溢出漏洞
01、漏洞信息详情
CNNVD编号:CNNVD-201803-1079[1]
危害等级:超危
CVE编号:CVE-2017-13253[2]-[4]
漏洞类型:权限许可和访问控制
发布时间:2018-03-05
威胁类型:远程
更新时间:2018-04-10
厂商:google
漏洞来源:VasilyVasiliev, Zinuo Han from Chengdu Security Response Center of Qihoo 360 Technology and Tamir Zahavi-Brunner (@tamir_zb) of Zimperium zLabs Team.
1●
漏洞简介
Android是美国谷歌(Google)公司和开放手持设备联盟(简称OHA)共同开发的一套以Linux为基础的开源操作系统。
Android 8.0版本和8.1版本中的CryptoPlugin.cpp文件的CryptoPlugin::decrypt存在提权漏洞,该漏洞源于程序缺少边界检测。远程攻击者可利用该漏洞执行任意代码或造成拒绝服务(越边界写入)。
2●漏洞公告
目前厂商已发布升级补丁以修复漏洞,补丁获取链接:
https://source.android.com/security/bulletin/2018-03-01
3●参考网址
来源:www.securityfocus.com
链接:
http://www.securityfocus.com/bid/103255
来源:source.android.com
链接:
https://source.android.com/security/bulletin/2018-03-01
来源:www.exploit-db.com
链接:
https://www.exploit-db.com/exploits/44291/
4●受影响实体
Google Android:8.0和Android:8.1。
02、漏洞分析
1●binder机制分析
对漏洞相关源代码进行分析,可以发现,堆溢出漏洞发生在/frameworks/av/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp中,如下图所示:
此函数的上层函数是/hardware/interfaces/drm/1.0/default/CryptoPlugin.cpp中的
数据结构SubSampl是在下面的文件中进行定义,具体代码如下所示:frameworks/native/include/media/hardware/CryptoAPI.h
数据结构SouceBuffer,DestinationBuffer的定义均位于ICrypto.h中,frameworks\av\media\libmedia\include\media\ICrypto.h
从参考文献[5]中摘录的调用过程如下:
从参考文献[5]中摘录的调用过程如下:
上述代码段用来判断source的大小是否正确,通过source.offset + offset(其实是subSamples起始地址偏移+source.size得出结果。
然后计算出源地址,srcPtr = base+source.offset+offset,也就是第一个subSamples的地址。计算过程没有问题。下面开始计算destination和dstPtr的地址。
121行代码判断缓冲区类型,这里是SHARED_MEMORY,进入122行代码。
也是先计算destBuffer的大小是否正确。计算过程没有问题。
然后计算destPtr的地址,destPtr = base + offset。这里的base其实就是source的起始地址。计算过程没有问题。这样看来确实都是正常的,不存在任何漏洞。
继续看上一层函数:/frameworks/av/drm/libmediadrm/ICrypto.cpp 中的
356行代码开始只是判断了destination的类型,并没有判断destination.offset加上total值是否大于destination.size。这里total值就是要处理的解密数据总和。因此在最上面那个函数里面发送了溢出。
根据参考文献[6],可以看到解密过程
2●PoC代码
PoC调用了很多头文件是来自源码中的。单纯的ndk无法编译。git上面有编译方法可供参考[7]。ubuntu物理机,源码要求:8.0以上,调试机器:nexus5x。不建议使用模拟器调试。
服务端调试命令:
客户端调试命令:
打断点,主要是三个关键函数:
android::BnCrypto::onTransact
android::CryptoHal::decrypt
clearkeydrm::CryptoPlugin::decrypt
先看android::BnCrypto::onTransact函数,然后使用adb shell 查看代码执行情况system/bin/icrypto_overflow,命中断点后单步调试,前两次分别调用createPlugin和setHeap,然后调用decrypt。
调用decrypt函数过程
单步查看实现逻辑。可能android源码命名空间的源码,上下文中无法打印出局部变量,只能通过观察寄存器。从反序列化中获取total的值。
读取后放到r9里面。单步调试,查看r9。
具体其他参数,可以同样单步调试进行查看,此处不再赘述。下面查看调用decrypt函数。
可以查看部分参数。下面直接查看memcpy函数。
r11 存放destPtr, r10存放srcPtr, r2存放拷贝大小,r5是offset。
使用vmmap命令,可以查看内存属性。
0xee186000是MemoryHeapBase的起始地址,大小为0x2000。
如果从0xee187fff覆盖,0xee187fff+0x2000 > 0xee188000的,这就导致堆溢出了,直接触发了堆保护页。
3●漏洞利用
通过Kali Linux查找漏洞相关信息[8],也可以通过git上公布的漏洞利用代码[9],如下所示:
03、补丁情况
Android Drm service堆溢出漏洞补丁信息可以参考以下网址:
https://android.googlesource.com/platform/frameworks/av/+/871412cfa05770cfd8be0a130b68386775445057%5E%21/#F0
直接在判断完destination的类型后,就判断dest->offset + totalSize不能大于dest->size。