Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
ResourcePoison — Writeup y exploit para CVE-2025-22441: Escalada de privilegios desde una app instalada al proceso SystemUI en Android debido al paso de ApplicationInfo no confiable a LoadedApk | Kitploit
Herramientas/GitHubGitHub/michalbednarski/resourcepoison
Seguridad AndroidEscalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónSeguridad MóvilPapers e Investigación
GitHubmichalbednarski/resourcepoison

ResourcePoison

Writeup y exploit para CVE-2025-22441: Escalada de privilegios desde una app instalada al proceso SystemUI en Android debido al paso de ApplicationInfo no confiable a LoadedApk

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio
1082963hace 0 añosRevisado por Kitploit

La corrección para este problema ha aparecido como CVE-2025-22441: boletín parche seguimiento

Pasando ApplicationInfo

ApplicationInfo es una estructura que define diversa información sobre una aplicación instalada, sobre todo la ruta al archivo apk desde el que se cargan los recursos y el código

Normalmente se pasa del sistema a las aplicaciones, sin embargo a veces hay casos en los que un llamador que no es del sistema podría proporcionar uno propio. Por ejemplo, en el pasado hubo una vulnerabilidad en el método bindBackupAgent(), donde un atacante podía pasar como parámetro su propio objeto ApplicationInfo con valores de uid y sourceDir que no se comprobaban contra las aplicaciones realmente instaladas en el sistema, porque ese método estaba pensado para ser llamado internamente por system_server, pero estaba expuesto a adb shell

Esta vez, sin embargo, he examinado de cerca el campo ApplicationInfo dentro de RemoteViews

RemoteViews es un objeto que describe una vista que puede provenir de otro proceso. Esto se usa sobre todo para los widgets de la pantalla de inicio, donde la aplicación que proporciona el widget construye RemoteViews y luego se "aplica" dentro del proceso de la pantalla de inicio

Otros lugares donde se usan RemoteViews son las notificaciones (aplicadas por el proceso SystemUI) y los diálogos de autocompletado (proporcionados por el servicio de autocompletado, aplicados por system_server)

El campo RemoteViews.mApplication se serializa a través de Parcel y, por tanto, puede provenir de procesos remotos y, siempre que se aplican RemoteViews, lo usa el siguiente método (fuente del fragmento):```java private Context getContextForResourcesEnsuringCorrectCachedApkPaths(Context context) { if (mApplication != null) { if (context.getUserId() == UserHandle.getUserId(mApplication.uid) && context.getPackageName().equals(mApplication.packageName)) { return context; } try { LoadedApk.checkAndUpdateApkPaths(mApplication); return context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found"); } }

return context;

}

Lo más interesante aquí es la llamada a `LoadedApk.checkAndUpdateApkPaths()`, ya que es un método estático y modificará algún estado global [(fuente del fragmento)](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/app/LoadedApk.java;l=2275-2302;drc=5916ee589c4880e2d8a1a9ad6dc852108e4c44c1)```java
public static void checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo) {
    // Get the LoadedApk from the cache
    ActivityThread activityThread = ActivityThread.currentActivityThread();
    if (activityThread == null) {
        Log.e(TAG, "Cannot find activity thread");
        return;
    }
    checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ true);
    checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ false);
}

private static void checkAndUpdateApkPaths(ActivityThread activityThread,
        ApplicationInfo expectedAppInfo, boolean cacheWithCode) {
    String expectedCodePath = expectedAppInfo.getCodePath();
    LoadedApk loadedApk = activityThread.peekPackageInfo(
            expectedAppInfo.packageName, /* includeCode= */ cacheWithCode);
    // If there is load apk cached, or if the cache is valid, don't do anything.
    if (loadedApk == null || loadedApk.getApplicationInfo() == null
            || loadedApk.getApplicationInfo().getCodePath().equals(expectedCodePath)) {
        return;
    }
    // Duplicate framework logic
    List<String> oldPaths = new ArrayList<>();
    LoadedApk.makePaths(activityThread, expectedAppInfo, oldPaths);

    // Force update the LoadedApk instance, which should update the reference in the cache
    loadedApk.updateApplicationInfo(expectedAppInfo, oldPaths);
}

Discutamos qué está ocurriendo en estos métodos

Primero estamos llamando a checkAndUpdateApkPaths de 3 parámetros con cacheWithCode establecido tanto en true como en false. El objeto LoadedApk puede construirse en dos modos, ya sea con mIncludeCode siendo true o false, lo que a nivel de SDK se corresponde con un Context con el flag CONTEXT_INCLUDE_CODE establecido o no

Ese método primero usará ActivityThread.peekPackageInfo(), que devolverá la instancia de LoadedApk ya almacenada en caché, por lo tanto, si la aplicación no construyó previamente un LoadedApk con el packageName e includeCode coincidentes, peekPackageInfo() devolverá null y checkAndUpdateApkPaths() no hará nada

Volviendo a RemoteViews.getContextForResourcesEnsuringCorrectCachedApkPaths(), tenemos context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED) allí, el flag CONTEXT_INCLUDE_CODE no fue especificado (lo mismo ocurre con los contextos pasados como argumento a ese método) y por lo tanto ese método siempre usará LoadedApk con mIncludeCode=false

Por lo tanto, para RemoteViews actualizar la versión con código es innecesario, ya que RemoteViews siempre usan Context sin código. El mensaje del commit solo dice que hay dos lugares donde ApplicationInfo puede estar en caché y creo que eliminar la actualización de la versión con código no causaría problemas aquí (ya que checkAndUpdateApkPaths() solo es usado por AppWidgetHostView y RemoteViews). El contraargumento a esto, sin embargo, es evitar la posibilidad de que varias cachés se desincronicen, y aunque eliminar la llamada con cacheWithCode=true elimina el impacto más severo de este error, no soluciona completamente el problema, ya que la modificación de solo recursos (en lugar de código) aún podría ser valiosa para un atacante

Descargar herramienta