
PoC pour CVE-2021-39749, permettant de lancer une Activity arbitraire sur Android 12L Beta
Ceci est un PoC pour CVE-2021-39749, qui permet de démarrer des activités d'autres applications sur Android 12L Beta, indépendamment de leurs paramètres permission et exported
Dans Android 12L, l'accès à TaskFragmentOrganizer (intentionnellement) ne nécessite plus la permission MANAGE_ACTIVITY_TASKS
L'utilisation de l'application fournie ici nécessite la désactivation des vérifications des API cachées, vous pouvez le faire via adb shell settings put global hidden_api_policy 1. Celles-ci ne constituent pas une frontière de sécurité et il existe des contournements connus basés sur des applications
Voici les commits corrigeant ce bug (et quelques autres liés mentionnés dans le rapport original) :
startActivityInTaskFragment ne repose plus sur Binder.getCallingUid()ResolverActivity a maintenant relinquishTaskIdentity activéSurfaceControl de TaskFragment n'est plus fourniActivityRecord#appToken à TaskFragmentOrganizer est désormais basée sur l'uid au lieu du pidVous pouvez vérifier android-12.1.0_r4, annuler les 3 premiers commits (ou les 2 premiers, l'application pourra toujours éteindre l'appareil (en démarrant ShutdownActivity), mais la case « Zoom and set alpha » ne fonctionnera pas)
(Le premier commit de cette liste aura des conflits de fusion dans les tests si vous essayez de l'annuler, mais vous pouvez les ignorer)
Binder.getCallingUid() qui retourne toujours l'uid systèmeLa méthode Binder.getCallingUid() retourne l'uid du processus qui a envoyé la transaction Binder actuellement traitée. Cet uid est stocké dans une variable locale au thread. Le code gérant la transaction peut appeler Binder.clearCallingIdentity() pour définir cette variable sur l'uid de son propre processus afin d'indiquer aux méthodes appelées plus tard pendant le traitement de la transaction que les vérifications de permission doivent être effectuées contre lui-même (le code gérant la transaction) et non contre l'appelant de la transaction Binder
Parfois, il y a des Binder.getCallingUid() qui sont toujours appelés après Binder.clearCallingIdentity(), retournant donc toujours l'uid du propre processus. Parfois cela se produit intentionnellement, par exemple dans ActivityTaskManagerService#startDreamActivity (bien que ce soit une façon plutôt alambiquée de faire Process.myUid() ou Os.getuid())
J'ai écrit pour moi-même un outil d'analyse statique (basé sur Soot) qui signale ces appels Binder.getCallingUid() (et d'autres vérifications de permission) qui ne peuvent se produire qu'après Binder.clearCallingIdentity(). (J'ai une logique personnalisée pour gérer l'IR Jimple/Shimple RI fournie par Soot, bien qu'il puisse y avoir une meilleure façon de le faire avec Soot, mais c'est ce que j'ai actuellement)
Dans Android 12L Beta, cet outil en a trouvé un dans ActivityStartController#startActivityInTaskFragment (Remarque : le code source n'était pas disponible à ce moment-là car les versions Beta ne sont pas open source, mais Shimple est généralement lisible, donc j'utilisais Soot aussi comme décompilateur Java)
startActivityInTaskFragmentDans le cadre du rapport d'analyse statique, j'ai obtenu la hiérarchie d'appels depuis l'implémentation de onTransact() (où l'appel Binder commence) jusqu'à startActivityInTaskFragment :
onTransact dans le code généré par aidl de IWindowOrganizerControllerWindowOrganizerController#applyTransaction (sans l'argument CallerInfo)WindowOrganizerController#applyTransaction (avec l'argument CallerInfo)WindowOrganizerController#applyHierarchyOpActivityStartController#startActivityInTaskFragmentJ'ai découvert que les appels Binder à applyTransaction sont présents dans la classe TaskFragmentOrganizer et j'ai décidé de l'utiliser comme wrapper plus pratique que de faire tous les appels Binder directement (ni l'un ni l'autre n'est une API publique, donc j'ai dû utiliser la réflexion de toute façon)
Tout d'abord, la méthode « 2. » appelle enforceTaskPermission, qui sur Android 12.0 vérifiait la permission MANAGE_ACTIVITY_TASKS réservée à la signature, que nous ne pouvions pas obtenir. Cependant, sur Android 12L, les règles ont été assouplies afin que certaines transactions puissent être effectuées sans permissions. Il s'est avéré qu'aucune des opérations nécessaires pour effectuer startActivityInTaskFragment ne requérait de permission (si la transaction avait un TaskFragmentOrganizer associé)