QQ拼音for Android v4.9.1 so劫持/感染

Intro

QQ拼音for Android v4.9.1的导出组件com.tencent.qqpinyin.voice.DownloadApkService没有对传入的下载地址进行过滤,导致任意文件下载,且没有对传入的文件名进行合法性校验,导致目录遍历。加上其本身Apk的特点,可以使用该组件感染/劫持so文件。
之前没注意QQ拼音已经归属搜狗,2015-04-27提交到了TSRC,告知已转交搜狗。至今漏洞依然存在,但从v4.9.2开始lib目录有所变化,无法感染/劫持。

漏洞细节

查看AndroidManifest.xml文件,发现com.tencent.qqpinyin.voice.DownloadApkService导出:

DownloadApkService关键代码如下:

所以,绑定了该服务即可通过mBinder进行远程调用。mBinder是DownloadApkService$3,实现的接口如下:

DownloadApkService$3的startDownload实际上调用的是DownloadApkService的download函数:

download函数如下:

所以,实际上调用的是DownloadApkService$DownLoadTask进行下载。程序预期在/storage/emulated/0/Tencent/QQInput/Apk/目录下写入文件,由于没有处理”../”,导致目录遍历,可以将文件写入任意位置。

利用方法

和其他Service的利用有点差别,远程调用Binder需要在绑定后使用transact进行调用,通过Parcel传递返回值和参数。每一个函数的对应调用号可以在IDownloadApkService$Stub中找到:

然后利用起来就十分简单了:

关于感染/劫持

在QQ拼音for Android v4.9.1这个版本中,apk运行时所需的so文件并没有保存在apk的lib目录下,而是保存在了Apk的/res/raw/目录下,运行的时候释放到/data/data/com.tencent.qqpinyin/app_lib/目录并加载运行。在Android系统中,App自身无法写入/data/data/[PACKAGE_NAME]/lib/目录,只可读取。QQ拼音for Android v4.9.1的这种设计则绕过这种设计,并且在加载时只做了文件是否存在的校验,并没有其他完整性校验。利用如下代码可以感染libsecurity.so文件:

伪造的libsecurity.so被加载的时候会drop原始的so,并调用原始的JNI_Onload。效果如图所示:
0ce82ad83ec2664e30ef2ec318ea00c5
完整代码请参考QQPinyinExp

其他

4.9.2后的版本,所用的so文件放在了lib目录下,无法直接写入。然而,com.tencent.connect.auth.AuthDialog会尝试加载的/data/data/com.tencent.qqpinyin/files/libwbsafeedit.so:

看起来这是腾讯SSO的一个SDK,但目前没发现能触发的操作。如果其他App也用了这个SDK,配合额其他类似的漏洞,也可以达到劫持和感染的目的。

发表评论