
PoC für CVE-2021-39749, der das Starten beliebiger Activities auf Android 12L Beta ermöglicht
Dies ist ein PoC für CVE-2021-39749, der das Starten von Aktivitäten anderer Apps auf Android 12L Beta unabhängig von deren permission- und exported-Einstellungen ermöglicht
In Android 12L erfordert der TaskFragmentOrganizer-Zugriff (absichtlich) nicht länger die MANAGE_ACTIVITY_TASKS-Berechtigung
Die Verwendung der hier bereitgestellten App erfordert das Deaktivieren der Hidden API Checks. Dies kannst du über adb shell settings put global hidden_api_policy 1 tun. Diese stellen keine Sicherheitsgrenze dar und es gibt bekannte app-basierte Umgehungen
Hier sind Commits, die diesen Fehler (und einige verwandte, die im ursprünglichen Bericht erwähnt wurden) beheben:
startActivityInTaskFragment verlässt sich nicht länger auf Binder.getCallingUid()ResolverActivity hat jetzt relinquishTaskIdentity aktiviertSurfaceControl von TaskFragment wird nicht länger bereitgestelltActivityRecord#appToken an TaskFragmentOrganizer gesendet wird, basiert jetzt auf uid statt pidDu kannst android-12.1.0_r4 auschecken und die ersten 3 Commits (oder die ersten 2) zurücknehmen. Die Anwendung kann das Gerät dann weiterhin herunterfahren (durch Starten von ShutdownActivity), aber das Kontrollkästchen „Zoom and set alpha" funktioniert nicht
(Der erste Commit aus dieser Liste führt zu Merge-Konflikten in Tests, wenn du versuchst, ihn zurückzunehmen, aber diese kannst du ignorieren)
Binder.getCallingUid(), das immer die System-uid zurückgibtDie Methode Binder.getCallingUid() gibt die uid des Prozesses zurück, der die aktuell verarbeitete Binder-Transaktion gesendet hat. Diese uid wird in einer thread-lokalen Variable gespeichert. Code, der eine Transaktion verarbeitet, kann Binder.clearCallingIdentity() aufrufen, um diese Variable auf die uid des eigenen Prozesses zu setzen. Dies zeigt Methoden, die später während der Transaktionsverarbeitung aufgerufen werden, an, dass Berechtigungsprüfungen gegen sich selbst (den Code, der die Transaktion verarbeitet) und nicht gegen den Aufrufer der Binder-Transaktion durchgeführt werden sollten
Manchmal gibt es Binder.getCallingUid()-Aufrufe, die immer nach Binder.clearCallingIdentity() aufgerufen werden und daher immer die uid des eigenen Prozesses zurückgeben. Manchmal geschieht dies absichtlich, zum Beispiel in ActivityTaskManagerService#startDreamActivity (obwohl dies ein eher umständlicher Weg ist, um Process.myUid() oder Os.getuid() zu verwenden)
Ich habe für mich selbst ein (auf Soot basierendes) statisches Analysetool geschrieben, das solche Binder.getCallingUid()-Aufrufe (und andere Berechtigungsprüfungen) meldet, die nur nach Binder.clearCallingIdentity() auftreten können. (Ich habe eine eigene Logik für die Verarbeitung der von Soot bereitgestellten Jimple/Shimple-IR, obwohl es möglicherweise einen besseren Weg mit Soot gibt, aber das ist, was ich derzeit habe)
In der Android 12L Beta fand dieses Tool einen solchen Aufruf in ActivityStartController#startActivityInTaskFragment (Hinweis: Der Quellcode war damals nicht verfügbar, da Beta-Versionen nicht Open Source sind, aber Shimple ist im Allgemeinen lesbar, daher habe ich Soot auch als Java-Dekompilierer verwendet)
startActivityInTaskFragment aufAls Teil des statischen Analyseberichts habe ich die Aufrufhierarchie von der onTransact()-Implementierung (wo der Binder-Aufruf beginnt) bis zu startActivityInTaskFragment erhalten:
onTransact im aidl-generierten Code von IWindowOrganizerControllerWindowOrganizerController#applyTransaction (ohne CallerInfo-Argument)WindowOrganizerController#applyTransaction (mit CallerInfo-Argument)WindowOrganizerController#applyHierarchyOpActivityStartController#startActivityInTaskFragmentIch habe festgestellt, dass Binder-Aufrufe an applyTransaction in der TaskFragmentOrganizer-Klasse vorhanden sind, und ich habe beschlossen, sie als bequemeren Wrapper zu verwenden, als alle Binder-Aufrufe direkt durchzuführen (keines davon ist eine öffentliche API, daher musste ich ohnehin Reflection verwenden)
Zunächst ruft Methode „2." enforceTaskPermission auf, das unter Android 12.0 die nur-signature-Berechtigung MANAGE_ACTIVITY_TASKS prüfte, die wir nicht erhalten konnten. Unter Android 12L wurden die Regeln jedoch gelockert, sodass bestimmte Transaktionen ohne Berechtigungen durchgeführt werden können. Es stellte sich heraus, dass keine der für startActivityInTaskFragment benötigten Operationen eine Berechtigung erforderte (wenn die Transaktion einen zugeordneten TaskFragmentOrganizer hatte)