关于libStagefright系列漏洞分析

文章对应着CVE-2015-{1538,1539,3824,3826,3827,3828,3829}7个CVE,具体映射关系目前不明。此次安全漏洞号称影响“95%”安卓手机的安全。通过跟进此次漏洞的攻击面来看,这种说法毫不夸张,外界报道的关于一个彩信就直接打下机器的说法也是可信的。但这也仅仅是众多攻击面中的一条而已。

1. 攻击面分析
libStagefright默认会被mediaserver使用,也就是说,如果恶意的视频文件有机会被mediaserver处理到,该漏洞就有机会触发,举例:

 如文件管理app,如果视频被存放在sdcard,那么打开文件管理app,下拉列表到露出视频,就会触发缩略图解析,漏洞触发
 图库app,点击本地图片会出现缩略图,如果视频在sdcard,或者download目录,这时候也会触发。
 微信同样受到影响。通过微信发送的视频,点击也会导致media server崩溃。此外,收到的视频即使用户不点击,后面在微信中发送图片时,也会造成前面gallery,文件管理器同样的效果,也会触发缩略图过程并溢出。

1

 在最新版的Chrome43版中打开一个video链接(mp4),无需点击自动触发

2

 开机同样是一个触发点,mediaprovider会扫描sd卡里的所有文件,并且尝试去解析,恩开机自启动

3
media framework的架构如下:基本上采用了android的media框架来开发的程序都会受到影响。

4
看到这里,想说的是,外界所谓的那些,关闭彩信功能保平安也就寻求个心理安慰吧。从根源上看大部分(有一个例外)都和整数计算的上溢/下溢相关,因为这个问题,间接导致了后续的内存破坏等相关的安全问题。

1.1. 代码分析

1.1.1. No1 heap 读越界


 

只有下面几种chunk_type才会触发分支parse3GPPMetaData:


 

以上parse3GPPMetaData会触发两个3gp格式的漏洞。
第一个setCString heap读越界,首先从文件中offset读size数据到buffer。


 

然后,这个类似strcpy,所以就是
mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);

https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r8/media//MetaData.cpp


 


 

注意到size是动态的,所以这里一般不会溢出,但会出现读越界。


 

读到的内容被保存到一个metadata中,或许可以泄漏(例如title, artist这些信息)
5
1.1.2. No2 heap 越界写

第二个是under flow,如果size<6,那么len16会很大,会对buffer(还是刚才的heap)后面很大一片内存作bswap_16操作,写的内容不太可控


 

根据前面的计算,这里的size就是chunk_data_size,代表这个chunk中除去header外的data size。计算方式如下:
off64_t data_offset = *offset + 8;在解析header过程中自然标记data开始的offset
off64_t chunk_data_size = *offset + chunk_size – data_offset;
所以chunk_size<14且>8即可。Chunk_size来自文件tag前面4字节。
1.1.3. No3 heap overflow

然后是mpeg tx3g tag的,chunk_size是uint,与size之和溢出,导致实际分配比size小的内存。后面的memcpy heap overflow,写入的data应该是可控的。

6

7
将trak修改为tx3g,然后前面的改为ffff

8

1.1.4. No4 heap 越界读

出现在covr这个tag处理时,chunk_data_size小于kSkipBytesOfDataBox时,setData会读过buffer的边界。由于setData会分配内存,但多半分配失败,所以可能也会导致向地址为0的内存写入。
9
1.1.5. No5 heap 越界写

当chunk_data_size=SIZE_MAX时,+1导致分配0长度的内存,后面的readAt会边读文件边写入buffer,在读到文件结束之前已经导致了heap write 越界。由于覆盖数据来自文件,所以内容与长度都是可控的。

9

1.1.6. No6 Integer overflow

处理stsc这种tag时,调用了setSampleToChunkParams方法

这个方法内有integer overflow,主要是循环过程中,在计算类似mSampleToChunkEntries[i].startChunk的时候,内部实际上是按照i*sizeof(SampleToChunkEntry)+ offset(startChunk)来计算的,这里可能overflow,但从这里看不一定造成内存破坏,可能会干扰执行逻辑。

https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r8/media/libstagefright/SampleTable.cpp


 

所以补丁增加了校验


 

1.1.7. No7 parseESDescriptor Integer overflow

这里的主要问题是只在开始检查了size>=3,然后就-2,–,后面又继续几次-2,-length都没法保证不溢出。


 

虽然没直接看到溢出的size造成影响,但可能会造成开发者未预料到的逻辑。


 

1.1.8. No8 SampleTable Integer overflow

https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r8/media/libstagefright/SampleTable.cpp

32位uint相乘,然后将结果转化为64位uint

这里存在溢出问题,虽然未看到直接的影响,但可能造成后面的检查误判。修复方法如下:


 

1.2. 总结

前面1-8个漏洞有相似之处。

No1 : 一段数据被计算strlen,然后分配内存并strcpy,但这段数据并非一定以’\0’结束,所以导致读越界

No2-5:都是tag前的4字节size没有校验,可以任意取值,导致一系列的size计算问题。如下图所示,所有tag4字节前面都有4字节的size:

No6-8:都是integer overflow,但没有看到直接内存破坏的错误。可能会造成数据异常等。

11

1.3. POC

1到5这5个漏洞的触发路径非常明了。都是在parseChunk遇到某种特殊tag时,分支处理逻辑出现问题。所以构造poc只需要修改对应的tag即可。

特别是2-4,都是tag前的4字节size出现问题。只需要调整对应的size。

以下的POC是针对no3,将其中一个trak tag修改为tx3g,然后将前面的size修改为4个FF


 

从trace看出,这里是通过binder来调用media server提供的接口,进而对视频处理解析过程崩溃。所以溢出在media server进程。
1.4. 防护

由于media是安卓中非常核心的一个服务(虽然权限不高),大量的功能都涉及到这个服务。如果仅仅stop media来停止这个服务,手机基本无法使用,例如无法显示出桌面。

service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm qcom_diag
ioprio rt 4

在短信app中,通过设置(可在小米,华为等手机中找到这个选项)可以关闭彩信自动下载,降低风险。

但这样无法防止例如sdcard根目录, 下载目录, bluetooth这些目录被通过各种渠道发送过来的恶意视频(浏览器自动下载,usb拷贝,bluetooth,微信等),当用户一旦打开文件浏览或图库app,甚至在浏览器中直接访问视频也会被攻击。

所以大家开心的等补丁吧!

转载自:http://xteam.baidu.com/?p=254    原文作者:xteam