
CVE-2022-20452 के लिए एक्सप्लॉइट, इंस्टॉल किए गए ऐप से सिस्टम ऐप (या किसी अन्य ऐप) तक Android पर विशेषाधिकार वृद्धि, recycle() के बाद Parcel का उपयोग करके LazyValue के माध्यम से।
Android 13 Parcel सीरियलाइज़ेशन तंत्र को सख्त करने के लिए कई संवर्द्धन प्रस्तुत करता है
यहाँ Android सुरक्षा और गोपनीयता टीम द्वारा किए गए संवर्द्धन पर प्रस्तुति है
यह बहुत अच्छा है, निश्चित रूप से कई कमज़ोरियों को समाप्त कर देता है या उन्हें अशोषणीय बना देता है। साथ ही वे मेरे पिछले शोषण को तोड़ने का वर्णन करते हैं, जो ऐप्स को अपने कोड को अन्य ऐप्स (सिस्टम ऐप्स सहित) में लोड करने की अनुमति देता है
लेकिन अब मैं एक नए शोषण के साथ वापस आया हूँ जो समान परिणाम प्राप्त करता है, हालाँकि अलग तरीके से। यह निम्नलिखित कमज़ोरियों पर निर्भर करता है जो उपरोक्त Parcel सख्तीकरण के दौरान पेश की गई थीं:
![एप्लिकेशन द्वारा टेक्स्ट प्रदर्शित करते हुए स्क्रीनशॉट। शीर्षक: LeakValue। मुख्य टेक्स्ट: 6 ValueLeaker-s बनाए गए। ActivityTaskManagerService लॉक किया जा रहा है। ActivityTaskManagerService लॉक किया गया। ActivityTaskManagerService अनलॉक किया जा रहा है। ActivityTaskManagerService अनलॉक किया गया। leakedBinders=[android.os.BinderProxy@f06702e]। लीक हुआ इंटरफ़ेस: android.app.IApplicationThread। कोड निष्पादन का अनुरोध किया जा रहा है। शेलकोड निष्पादित किया गया है uid=1000 pid=6904 packageName=com.android.settings uid=1000(system) gid=1000(system) groups=1000(system),1007(log),1065(reserved_disk),1077(external_storage),3001(net_bt_admin),3002(net_bt),3003(inet),3007(net_bw_acct),9997(everybody) context=u:r:system_app:s0 में। स्क्रीन के नीचे दो बटन हैं: START और MANUAL TESTING](Screenshot_20220723-081920.png)
(साथ ही ऐप निष्पादन से logcat, लॉग में शोषण शोरगुल वाला है)
Parcel और Parcelable असंगति बग्स का परिचयAndroid का Parcel वर्ग प्रक्रियाओं के बीच संचार का आधार है
ऑब्जेक्ट्स को Parcel में लिखने की अनुमति देने के लिए वे Parcelable इंटरफ़ेस लागू कर सकते हैं, उदाहरण के लिए (AOSP से कॉपी किया गया):```java
public class UsbAccessory implements Parcelable {
public static final Parcelable.Creator CREATOR =
new Parcelable.Creator() {
public UsbAccessory createFromParcel(Parcel in) {
String manufacturer = in.readString();
String model = in.readString();
String description = in.readString();
String version = in.readString();
String uri = in.readString();
IUsbSerialReader serialNumberReader = IUsbSerialReader.Stub.asInterface(
in.readStrongBinder());
return new UsbAccessory(manufacturer, model, description, version, uri,
serialNumberReader);
}
};
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeString(mManufacturer);
parcel.writeString(mModel);
parcel.writeString(mDescription);
parcel.writeString(mVersion);
parcel.writeString(mUri);
parcel.writeStrongBinder(mSerialNumberReader.asBinder());
} }
ध्यान दें कि `Parcel` आंतरिक रूप से उस स्थिति को संग्रहीत करता है जिस पर write या read किया जाता है, `readString()` डेटा को String में parse करता है और साथ ही स्थिति को आगे बढ़ाता है। उस स्थिति को [`dataPosition()`](https://developer.android.com/reference/android/os/Parcel#dataPosition())/[`setDataPosition()`](https://developer.android.com/reference/android/os/Parcel#setDataPosition(int)) के माध्यम से मैन्युअल रूप से प्राप्त/सेट किया जा सकता है। `Parcelable` इंटरफ़ेस के कार्यान्वयन को यह सुनिश्चित करना चाहिए कि उनके `writeToParcel` और `createFromParcel` समान मात्रा में डेटा लिखें/पढ़ें, अन्यथा बाद के सभी read गलत offsets से डेटा प्राप्त करेंगे।
[`Bundle`](https://developer.android.com/reference/android/os/Bundle) (key-value मैप जिसे प्रक्रियाओं के बीच भेजा जा सकता है) में [विभिन्न प्रकार की वस्तुएँ हो सकती हैं जिन्हें `writeValue()` के माध्यम से Parcel में लिखा जा सकता है](https://cs.android.com/android/platform/superproject/+/android-12.1.0_r8:frameworks/base/core/java/android/os/Parcel.java;l=1792-1937)। जब `Bundle` की सामग्री `Parcel` से पढ़ी जाती है, तो सिस्टम में उपलब्ध कोई भी `Parcelable` वर्ग वहाँ पढ़ा जा सकता है।
`Bundle` संपूर्ण parcelled डेटा की लंबाई `Parcel` में लिखकर और फिर [मूल Parcel के प्रासंगिक भाग को `mParcelledData` में संग्रहीत द्वितीयक Parcel में प्रतिलिपि करके](https://cs.android.com/android/platform/superproject/+/android-12.1.0_r8:frameworks/base/core/java/android/os/BaseBundle.java;l=1675-1683) सामग्री के वास्तविक parsing को स्थगित करता है (यह उदाहरण के लिए [`Activity.onSaveInstanceState()`](https://developer.android.com/reference/android/app/Activity#onSaveInstanceState(android.os.Bundle)) को ऐसे `Parcelable` प्रदान करने की अनुमति देता है जो `system_server` में उपलब्ध नहीं हैं; पूरा `Bundle` तब बिना सामग्री parse किए verbatim `system_server` को और वापस भेज दिया जाता है)।
हालाँकि, एक बार जब `Bundle` में किसी भी मान तक पहुँचा गया, तो `Bundle` के अंदर के सभी मान [unparcelled कर दिए गए](https://cs.android.com/android/platform/superproject/+/android-12.1.0_r8:frameworks/base/core/java/android/os/BaseBundle.java;l=227-313) और [प्रत्येक मौजूदा key-value जोड़ी को parse किया गया](https://cs.android.com/android/platform/superproject/+/android-12.1.0_r8:frameworks/base/core/java/android/os/Parcel.java;l=3613-3632)। यदि ऐसे मानचित्र में ऐसा `Parcelable` था जिसमें असंतुलित `writeToParcel` और `createFromParcel` विधियाँ थीं और बाद में ऐसा `Bundle` किसी अन्य प्रक्रिया को अग्रेषित किया गया, तो उस अन्य प्रक्रिया को `Bundle` की भिन्न सामग्री दिखाई दे सकती थी। इसने सिस्टम में उपलब्ध वर्गों में ऐसे सभी [mismatch को सिस्टम भेद्यता बना दिया](https://github.com/michalbednarski/ReparcelBug), क्योंकि [सिस्टम में ऐसे स्थान हैं जहाँ `Bundle` को सुरक्षित होने के लिए निरीक्षित किया जाता है](https://cs.android.com/android/platform/superproject/+/android-12.1.0_r8:frameworks/base/services/core/java/com/android/server/accounts/AccountManagerService.java;l=5037-5046) और फिर उसे किसी अन्य प्रक्रिया को अग्रेषित किया जाता है।
इस writeup में मैं ऐसे `Bundle` को self-changing `Bundle` कह रहा हूँ जो एक सामग्री प्रस्तुत करता है और अग्रेषित किए जाने के बाद दूसरी सामग्री प्रस्तुत करता है।