
CVE-2021-39749 के लिए PoC, जो Android 12L Beta पर मनमाना Activity शुरू करने की अनुमति देता है
यह CVE-2021-39749 के लिए PoC है, जो Android 12L Beta पर उनकी permission और exported सेटिंग्स की परवाह किए बिना अन्य ऐप्स की activities शुरू करने की अनुमति देता है
Android 12L में TaskFragmentOrganizer एक्सेस (जानबूझकर) अब MANAGE_ACTIVITY_TASKS permission की आवश्यकता नहीं रखता
यहाँ दिए गए ऐप का उपयोग करने के लिए Hidden API Checks को अक्षम करना आवश्यक है, आप इसे adb shell settings put global hidden_api_policy 1 के माध्यम से कर सकते हैं। ये सुरक्षा सीमा नहीं हैं और ज्ञात ऐप-आधारित बाईपास मौजूद हैं
इस बग (और मूल रिपोर्ट में उल्लिखित कुछ संबंधित) को ठीक करने वाले commits यहाँ हैं:
startActivityInTaskFragment अब Binder.getCallingUid() पर निर्भर नहीं रहताResolverActivity में अब relinquishTaskIdentity सक्षम हैTaskFragment का SurfaceControl अब प्रदान नहीं किया जाताActivityRecord#appToken को TaskFragmentOrganizer को भेजने का निर्णय अब pid के बजाय uid पर आधारित हैआप android-12.1.0_r4 checkout कर सकते हैं, पहले 3 commits revert करें (या पहले 2, एप्लिकेशन फिर भी डिवाइस को बंद करने में सक्षम होगा (ShutdownActivity शुरू करके), लेकिन "Zoom and set alpha" checkbox काम नहीं करेगा)
(उस सूची का पहला commit revert करने पर tests में merge conflicts होंगे, लेकिन आप उन्हें अनदेखा कर सकते हैं)
Binder.getCallingUid() जो हमेशा system uid लौटाता हैBinder.getCallingUid() विधि उस प्रक्रिया का uid लौटाती है जिसने वर्तमान में संसाधित Binder transaction भेजा है। वह uid thread-local variable में संग्रहीत होता है। Transaction को संभालने वाला कोड Binder.clearCallingIdentity() कॉल कर सकता है ताकि उस variable को अपनी प्रक्रिया के uid पर सेट किया जा सके, यह दर्शाने के लिए कि transaction handling के दौरान बाद में कॉल किए गए methods में permission checks स्वयं के विरुद्ध किए जाने चाहिए, न कि Binder transaction के caller के विरुद्ध
कभी-कभी Binder.getCallingUid() ऐसे होते हैं जो हमेशा Binder.clearCallingIdentity() के बाद कॉल किए जाते हैं, इसलिए हमेशा अपनी प्रक्रिया का uid लौटाते हैं। कभी-कभी यह जानबूझकर होता है, उदाहरण के लिए ActivityTaskManagerService#startDreamActivity में (हालांकि यह Process.myUid() या Os.getuid() करने का काफी जटिल तरीका है)
मैंने अपने लिए एक (Soot-आधारित) static analysis tool लिखा है जो ऐसे Binder.getCallingUid() कॉल्स (और अन्य permission checks) की रिपोर्ट करता है जो केवल Binder.clearCallingIdentity() के बाद हो सकते हैं। (मेरे पास Soot द्वारा प्रदान किए गए Jimple/Shimple IR को संभालने के लिए custom logic है, हालांकि Soot के साथ ऐसा करने का बेहतर तरीका हो सकता है, लेकिन अभी मेरे पास यही है)
Android 12L Beta में उस tool ने ActivityStartController#startActivityInTaskFragment में एक पाया (नोट: source code तब उपलब्ध नहीं था क्योंकि Beta releases open source नहीं हैं, लेकिन Shimple आम तौर पर पठनीय है इसलिए मैं Soot को Java decompiler के रूप में भी उपयोग कर रहा था)
startActivityInTaskFragment को कैसे कॉल करेंStatic analysis रिपोर्ट के भाग के रूप में मुझे onTransact() implementation (जहाँ Binder call शुरू होता है) से startActivityInTaskFragment तक call hierarchy मिली:
IWindowOrganizerController के aidl-generated कोड में onTransactWindowOrganizerController#applyTransaction (बिना CallerInfo argument के)WindowOrganizerController#applyTransaction (CallerInfo argument के साथ)WindowOrganizerController#applyHierarchyOpActivityStartController#startActivityInTaskFragmentमैंने पाया कि TaskFragmentOrganizer class में applyTransaction के Binder calls मौजूद हैं और मैंने इसे सभी Binder calls सीधे करने की तुलना में अधिक सुविधाजनक wrapper के रूप में उपयोग करने का निर्णय लिया (न तो public API है इसलिए मुझे वैसे भी reflection का उपयोग करना पड़ा)
सबसे पहले, विधि "2." enforceTaskPermission कॉल करती है, जो Android 12.0 पर केवल signature-वाली MANAGE_ACTIVITY_TASKS permission की जाँच करती थी जो हमें नहीं मिल सकती थी, हालाँकि Android 12L पर नियम शिथिल किए गए थे ताकि कुछ transactions बिना permissions के किए जा सकें। यह पता चला कि startActivityInTaskFragment करने के लिए आवश्यक कोई भी operation permission की आवश्यकता नहीं रखता (यदि transaction में TaskFragmentOrganizer जुड़ा हो)
इसलिए हम HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT perform करना चाहते हैं। ऐसा करने के लिए हमारे पास mLaunchTaskFragments में हमारा TaskFragment registered होना चाहिए अन्यथा "Not allowed to operate with invalid fragment token" exception रिपोर्ट की जाएगी