Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
OrganizerTransaction — CVE-2021-39749 के लिए PoC, जो Android 12L Beta पर मनमाना Activity शुरू करने की अनुमति देता है | Kitploit
उपकरण/GitHubGitHub/michalbednarski/organizertransaction
एंड्रॉइड सुरक्षाभेद्यता विश्लेषणशोषणमोबाइल ऐप पेंटेस्टिंगमोबाइल सुरक्षा
GitHubmichalbednarski/organizertransaction

OrganizerTransaction

CVE-2021-39749 के लिए PoC, जो Android 12L Beta पर मनमाना Activity शुरू करने की अनुमति देता है

रिपॉजिटरी देखें

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें
37114 साल पहलेKitploit द्वारा समीक्षित

यह 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 यहाँ हैं:

  1. startActivityInTaskFragment अब Binder.getCallingUid() पर निर्भर नहीं रहता
  2. ResolverActivity में अब relinquishTaskIdentity सक्षम है
  3. (अन्य activities शुरू करने के लिए आवश्यक नहीं, लेकिन उन्हें स्क्रीन के चारों ओर reposition करने और उन्हें transparent और tap-jackable बनाने की अनुमति देता है) TaskFragment का SurfaceControl अब प्रदान नहीं किया जाता
  4. (यहाँ कोड में नहीं दिखाया गया, मुद्दा केवल मूल रिपोर्ट में उल्लिखित है) 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 मिली:

  1. IWindowOrganizerController के aidl-generated कोड में onTransact
  2. WindowOrganizerController#applyTransaction (बिना CallerInfo argument के)
  3. WindowOrganizerController#applyTransaction (CallerInfo argument के साथ)
  4. WindowOrganizerController#applyHierarchyOp
  5. ActivityStartController#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 रिपोर्ट की जाएगी

हम ऐसे TaskFragment को HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT के माध्यम से register कर सकते हैं, जो createTaskFragment() कॉल करता है

(PoC कोड में ये transactions SecondActivity में भेजे जाते हैं: HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT initOrganizerAndFragment() द्वारा भेजा जाता है और HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT startActivityInOrganizer द्वारा भेजा जाता है)

तो यह हमें startActivityInTaskFragment कॉल करने की अनुमति देता है और यहाँ शुरू की गई Activities के Intents system uid से आने वाले माने जाते हैं, लेकिन यह पता चलता है कि यह अपने आप में हमें कुछ भी करने नहीं देता: system द्वारा शुरू की गई activities URI grants नहीं कर सकतीं और यदि हम किसी अन्य ऐप की activity launch करने का प्रयास करते हैं तो हमें canEmbedActivity check द्वारा रोक दिया जाएगा

canEmbedActivity को बायपास करना

आइए canEmbedActivity पर फिर से नज़र डालें: embedding की अनुमति है यदि taskFragment.getTask().effectiveUid system का uid है या launched app के uid से मेल खाता है। हमें ऐसे task में होना होगा जिसका effectiveUid system है

साथ ही createTaskFragment() पर वापस जाएँ: TaskFragment का निर्माण केवल तभी allowed था जब rootActivity.getUid() != ownerActivity.getUid()। इसका मतलब है कि हमारी activity को उस Task के back-stack के नीचे होना होगा जिसमें वह है

हमें नया Task launch करना होगा (Intent.FLAG_ACTIVITY_NEW_TASK के माध्यम से) जिसमें system uid से संबंधित Activity होगी (ताकि Task#effectiveUid AID_SYSTEM पर सेट हो) और फिर वह Activity हमारी Activity शुरू करेगी (उसी Task के भीतर) और finish() स्वयं को (ताकि हमारी Activity उस task की root बन जाए जिससे हमें createTaskFragment() का उपयोग करने की अनुमति मिले)

ऐसी ही एक Activity ChooserActivity है। Chooser आमतौर पर "share" विकल्प चुनने के बाद यह चुनने के लिए उपयोग किया जाता है कि उपयोगकर्ता किस ऐप का उपयोग करना चाहता है। ChooserActivity में हालाँकि AndroidManifest.xml में android:relinquishTaskIdentity="true" सेट है, जिसका अर्थ है कि जब यह कोई अन्य Activity launch करती है तो यह Task#effectiveUid को नए-launched app के uid के साथ overwrite कर देगी

(relinquishTaskIdentity केवल तब काम करता है जब Task में पहले ऐप द्वारा उपयोग किया जाता है और केवल system apps के लिए, इसलिए हम स्वयं relinquishTaskIdentity का उपयोग नहीं कर सकते और अपने Task के Task#effectiveUid को overwrite करने के लिए system app launch नहीं कर सकते)

ऐसी ही एक और Activity (जो हमारी Activity शुरू कर सकती है और स्वयं finish() कर सकती है) ResolverActivity है। इसका उपयोग implicit Intent शुरू करते समय किया जाता है जो कई Activities में resolve होता है। Resolver (Chooser के विपरीत) choice याद रखने का विकल्प प्रदान करता है, जिससे आप (फोन के उपयोगकर्ता के रूप में) इन दोनों को अलग कर सकते हैं। ResolverActivity में relinquishTaskIdentity सेट नहीं था, हालाँकि Resolver उपलब्ध विकल्पों को खोजने के लिए अपना स्वयं का Intent उपयोग करता है (जबकि Chooser Extras में प्रदान किया गया Intent लेता है)। यह exploitation के लिए एक समस्या बन जाती है क्योंकि Resolver द्वारा चयनित Activity launch करते समय उपयोग किए जाने वाले Intent flags वही होंगे जो Resolver को launch करने के लिए उपयोग किए गए थे और:

  • यदि हम Intent.FLAG_ACTIVITY_NEW_TASK सेट नहीं करते हैं, तो Resolver हमारे Task के भीतर launch होगा जिसमें पहले से ही effectiveUid स्थायी रूप से सेट है
  • यदि हम Intent.FLAG_ACTIVITY_NEW_TASK सेट करते हैं, तो Resolver selection को एक और Task में launch करेगा, जिसमें फिर effectiveUid launched app से संबंधित सेट होगा

इन समस्याओं का समाधान दोनों का उपयोग करना है:

  1. पहले हम ChooserActivity launch करते हैं: हम इसके Intent को प्रदान करते हैं:
    • Intent.FLAG_ACTIVITY_NEW_TASK, ताकि Chooser नए Task में launch हो (जिसमें system का effectiveUid होगा लेकिन केवल अगली Activity launch तक)
    • Intent.EXTRA_INTENT एक ऐसे Intent पर सेट जो किसी भी Activities से मेल नहीं खाता और Chooser में केवल बचे विकल्प Intent.EXTRA_INITIAL_INTENTS से आएंगे
    • Intent.EXTRA_INITIAL_INTENTS जिसमें एक-तत्व वाली array हो: वह Intent जिसे हम Chooser से launch कराना चाहते हैं (जब केवल एक विकल्प होता है तो Chooser और Resolver दोनों prompt छोड़ देते हैं और तुरंत केवल विकल्प launch करते हैं और स्वयं finish() करते हैं)
  2. फिर ResolverActivity को ChooserActivity द्वारा launch किया जाता है:
    • Resolver में relinquishTaskIdentity सेट नहीं था, इसलिए अब system पर सेट है और इस Task में launch की गई अगली Activities की परवाह किए बिना वैसा ही रहेगा

(PoC ऐप में इन चरणों की तैयारी FirstActivity में की जाती है)

TaskFragmentOrganizer के साथ अन्य tricks

TaskFragmentOrganizer को onTaskFragmentAppeared callback के माध्यम से एक SurfaceControl प्राप्त हुआ और उस SurfaceControl का उपयोग करके launch की गई Activity को scale किया जा सकता है और transparent बनाया जा सकता है, जबकि यह अभी भी touch events प्राप्त करेगी और obscured नहीं मानी जाएगी (इसलिए tap-jacking-संरक्षित elements पर अभी भी tap किया जा सकता है)

आप इसे PoC ऐप में "Zoom and set alpha" checkbox चेक करके देख सकते हैं

यह ऊपर fixes सूची के commit "3." द्वारा ठीक किया गया है


एक और बात यह है कि TaskFragment के अंदर चल रही Activities के ActivityRecord#appToken-s TaskFragmentOrganizer callbacks को पास किए गए। यह सूची केवल उसी प्रक्रिया के भीतर Activities के tokens शामिल करने के लिए फ़िल्टर की गई थी, हालाँकि जाँच TaskFragmentOrganizer के pid की तुलना उस Activity के pid से करके की गई थी जिसका appToken हम प्राप्त कर सकते थे। मैंने वास्तव में जाँच नहीं की है लेकिन मुझे लगता है कि एप्लिकेशन TaskFragmentOrganizer बना सकता है, इसे शुरू में बनाने के लिए उपयोग की गई प्रक्रिया से बाहर निकल सकता है और उसका pid किसी अन्य ऐप की Activity के pid के रूप में पुनः उपयोग किया जा सकता है ताकि उसका appToken प्राप्त किया जा सके। यहाँ commit है (ऊपर fixes सूची में "4.") जो सत्यापन को pid-आधारित से uid-आधारित में बदलता है (ऐसा लगता है कि यह commit मेरी रिपोर्ट से स्वतंत्र रूप से किया गया था हालाँकि (इसके बाद भी))

एक बार attacker को किसी Activity का appToken मिल जाता है तो वे onActivityResult() calls inject कर सकते हैं (भले ही target app ने स्वयं startActivityForResult() कॉल न किया हो) और संभवतः savedInstanceState के साथ छेड़छाड़ कर सकते हैं (activityStopped() कॉल करके, यह मानते हुए कि attacker target application द्वारा उस method को कॉल करने के साथ race जीत सकता है और अतिरिक्त कॉल crash के कारण state खोने का कारण नहीं बनेगी)

मैंने जाँच नहीं की है कि क्या यह इस मामले में किया जा सकता है, हालाँकि पहले, CVE-2020-0001 के साथ (हाँ, मुझे fancy number मिला), मैं system settings app को बिना user interaction के मेरा AccessibilityService सक्षम करने के लिए धोखा देने हेतु savedInstanceState tampering और onActivityResult() injection का उपयोग करने में सक्षम था, लेकिन यह किसी और समय की कहानी है

टूल डाउनलोड करें
Task#effectiveUid
  • Intent में Intent.FLAG_ACTIVITY_NEW_TASK नहीं है, इसलिए अगली Activity उसी Task के भीतर launch होती है
  • Intent action गैर-मानक पर सेट है, केवल हमारे द्वारा अपने ऐप में घोषित <intent-filter> से मेल खाता है, इसलिए Resolver तुरंत हमारी Activity launch करने के लिए आगे बढ़ता है
  • ResolverActivity हमारी Activity launch करती है
    • अब हम ऐसे Task में हैं जिसका effectiveUid AID_SYSTEM है, इसलिए canEmbedActivity() कुछ भी अनुमति देता है
    • Chooser और Resolver दोनों ने स्वयं को finish कर लिया है, इसलिए हम Task में root Activity हैं और हमें createTaskFragment() का उपयोग करने की अनुमति है