Skip to content

Android Package Context created without security restrictions

Android Package Context created without security restrictions

Description

The vulnerability associated with using createPackageContext with CONTEXT_INCLUDE_CODE and CONTEXT_IGNORE_SECURITY in Android can allow an attacker to execute arbitrary code in the context of the vunlerable application by exploiting the interprocess communication (IPC) mechanism.

In Android, each app is sandboxed to prevent unauthorized access to resources and system functionality. However, apps can interact with each other through IPC mechanisms such as createPackageContext. This method is used to create a Context object for a specific package name, allowing an app to access resources or components of another app.

By requesting the android.permission.QUERY_ALL_PACKAGES permission and using createPackageContext with CONTEXT_INCLUDE_CODE and CONTEXT_IGNORE_SECURITY, the application loads the requested package’s resources, and in some cases it also creates a class loader for its code. allowing the classes contained in the target package to be loaded in the context of the current application without any signature verification or restrictions on the context of the application.

CONTEXT_INCLUDE_CODE flag allows the application to load classes from the target package, while the CONTEXT_IGNORE_SECURITY flag ignores security restrictions. Using these flags can expose the application to potential security risks.

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import java.lang.reflect.Method;
import java.util.List;

public final class InsecurePackageContext {

    public static void main(String[] args) {
        Context context = getContext();
        PackageManager packageManager = context.getPackageManager();

        List<PackageInfo> installedPackages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA);

        for (PackageInfo info : installedPackages) {
            String packageName = info.packageName;

            if (packageName.startsWith("co.ostorlab.")) {
                try {
                    Context packageContext = context.createPackageContext(packageName,
                            Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);

                    Class<?> loaderClass = packageContext.getClassLoader().loadClass("co.ostorlab.payload");
                    Method updateMethod = loaderClass.getMethod("Update", Context.class);
                    updateMethod.invoke(null, context);

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

Recommendation

To mitigate the vulnerability associated with insecure package context creation using createPackageContext with CONTEXT_INCLUDE_CODE and CONTEXT_IGNORE_SECURITY flags, developers should:

1- Avoid using createPackageContext by baking any necessary components into the app itself rather than using separate apk files.

2- if using createPackageContext is necessary, avoid using the flags CONTEXT_INCLUDE_CODE and CONTEXT_IGNORE_SECURITY, instead use CONTEXT_RESTRICTED which may disable specific features but makes the application more robust against third party application attacks.

3- When checking if the package is in the list of installed packages, avoid loose comparisons like startsWith or endsWith, instead try matching the package name exactly

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import java.lang.reflect.Method;
import java.util.List;

public final class InsecurePackageContext {

    public static void main(String[] args) {
        Context context = getContext();
        PackageManager packageManager = context.getPackageManager();

        List<PackageInfo> installedPackages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA);

        for (PackageInfo info : installedPackages) {
            String packageName = info.packageName;

            if (packageName.equals("co.ostorlab.plugins.camera")) {
                try {
                    Context packageContext = context.createPackageContext(packageName,
                            Context.CONTEXT_RESTRICTED);

                    Class<?> loaderClass = packageContext.getClassLoader().loadClass("co.ostorlab.plugins.camera.Main");
                    Method updateMethod = loaderClass.getMethod("Update", Context.class);
                    updateMethod.invoke(null, context);

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

Standards

  • OWASP_MASVS_L1:
    • MSTG_PLATFORM_2
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_2
  • CWE_TOP_25:
  • GDPR:
    • ART_5
    • ART_25
    • ART_32
    • ART_35
  • PCI_STANDARDS:
    • REQ_6_2
    • REQ_6_3
    • REQ_11_3