/ CODE EXECUTION, ANDROID

Android: arbitrary code execution via third-party package contexts

There are apps for Android that have the ability to add extra functionality by using external modules. Some load native libraries or third-party dex or app files, but in this article we will be looking at modules that are installed from markets as third-party apps and are used by the main app as a set of additional functions: camera filters, themes, font sets, etc. According to Oversecured statistics, at least one in every 50 popular apps are subject to this vulnerability.

post-header-image

After the module is installed, the main app begins to search for it among all apps installed on the same device by using certain templates (package name prefix, values from AndroidManifest.xml). If the verification is weak, an attacker's app may be treated as a legitimate module. At the moment the module is loaded, code from it is executed in the context of the main app – leading to arbitrary code execution. As a result, the attacker may gain the ability to steal any sensitive data that the user enters into the app or that the app receives from the server, as well as to substitute this data, disclose financial details, and track the user.

Do you want to check your mobile apps for such types of vulnerabilities? Oversecured mobile apps scanner provides an automatic solution that helps to detect vulnerabilities in Android and iOS mobile apps. You can integrate Oversecured into your development process and check every new line of your code to ensure your users are always protected.

Start securing your apps by starting a free 2-week trial from Quick Start, or you can book a call with our team or contact us to explore more.

The essence of the vulnerability

Such apps can scan the device as follows

public static void searchModules(Context context) {
    for (PackageInfo info : context.getPackageManager().getInstalledPackages(0)) {
        String packageName = info.packageName;
        if (packageName.startsWith("com.victim.module.")) {
            processModule(context, packageName);
        }
        //...

and then work, generally insecurely, with these third-party apps

public static void processModule(Context context, String packageName) {
    Context appContext = context.createPackageContext(packageName, CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY);
    ClassLoader classLoader = appContext.getClassLoader();
    try {
        Object interface = classLoader.loadClass("com.victim.MainInterface")
                .getMethod("getInterface")
                .invoke(null);
        //...

In this example the vulnerable app obtains the ClassLoader of any app whose package begins with com.victim.module., tried to find com.victim.MainInterface and call its getInterface method. The danger is that an attacker can create their own app with a package name that begins with the right prefix, create the specified class with this method, and include in that method code that will then be executed in the context of the victim app.

package com.victim;

public class MainInterface {
    public static Object getInterface() {
        try {
            Runtime.getRuntime().exec("...attacker..controlled..command...").waitFor();
        } catch (Throwable th) {
        }
        return null;
    }
}

In fact, apps cannot just call methods using the Java Reflection API: they can also create class instances, obtain field values, etc., all of which also leads to arbitrary code execution.

Oversecured finds this kind of vulnerability automatically: for an example see our Oversecured Vulnerable Android App and Sample Report

vulnerability

Recommendations

A good defense in this case would be to verify the signature of the current app and the module. The method could be rewritten as follows:

public static void searchModules(Context context) {
    PackageManager packageManager = context.getPackageManager();
    for (PackageInfo info : packageManager.getInstalledPackages(0)) {
        String packageName = info.packageName;
        if (packageName.startsWith("com.victim.module.")
                && packageManager.checkSignatures(packageName, context.getPackageName()) == PackageManager.SIGNATURE_MATCH) {

            processModule(context, packageName);
        }
        //...

The attacker would not be able to sign their app with the same certificate that had been used to sign the app that was being attacked, which would prevent the illegitimate module being loaded.

Protect your apps today!

It can be challenging to keep track of security issues that appear daily during the app development process. Drop us a line and we'll help you automate this process internally, saving tons of resources with Oversecured.