
CVE-2024-34740 के लिए राइटअप और एक्सप्लॉइट — Android के BinaryXmlSerializer में इंटीजर ओवरफ्लो से system_server फ़ाइल राइट और फिर सामान्य इंस्टॉल किए गए ऐप से system_server कोड निष्पादन

यहाँ वर्णित समस्या के फिक्स CVE-2024-34740 / A-307288067 के अंतर्गत सामने आए:
Android system_server के अंदर, कई सेवाएँ रिबूट्स के बीच अपनी स्थिति को XML फ़ाइलों में संग्रहीत करती हैं```
$ adb shell su 0 find /data/system -name '*.xml' | sort
/data/system/appops_accesses.xml
/data/system/cachequota.xml
/data/system/device_policies.xml
/data/system/device_policy_state.xml
/data/system/display-manager-state.xml
/data/system/input-manager-state.xml
/data/system/inputmethod/subtypes.xml
/data/system/install_sessions.xml
/data/system/job/jobs_1000.xml
/data/system/job/jobs_10131.xml
/data/system/log-files.xml
/data/system/netpolicy.xml
/data/system/notification_policy.xml
/data/system/overlays.xml
/data/system/packages.xml
/data/system/package-watchdog.xml
/data/system/sensor_privacy_impl.xml
/data/system/sensor_privacy.xml
/data/system/shortcut_service.xml
/data/system/users/0/app_idle_stats.xml
/data/system/users/0/appwidgets.xml
/data/system/users/0/package-restrictions.xml
/data/system/users/0/settings_global.xml
/data/system/users/0/settings_secure.xml
/data/system/users/0/settings_system.xml
/data/system/users/0/wallpaper_info.xml
/data/system/users/0.xml
/data/system/users/userlist.xml
/data/system/watchlist_settings.xml
ऐतिहासिक रूप से ये सादे टेक्स्ट XML फ़ाइलें होती थीं जिनमें इंडेंटेशन होता था, जिससे डेवलपर्स इन्हें आसानी से पढ़ पाते थे, हालाँकि [Android 12 में उस प्रारूप का नया बाइनरी संस्करण पेश किया गया, जिसमें कहा गया कि `system_server` द्वारा बिताए गए कुल समय का 1.5% इन XML ऑपरेशनों पर खर्च होता है](https://android.googlesource.com/platform/frameworks/base/+/4ccea8796991d678ead4399130ec31edf63ff4fa%5E%21/)
गौरतलब है कि यह प्रारूप केवल सिस्टम द्वारा आंतरिक रूप से उपयोग किया जाता है और इसमें मैजिक वैल्यू `"ABX\x00"` वाली फ़ाइलें होती हैं। यह [APK के अंदर उपयोग किए जाने वाले प्रारूप](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/libs/androidfw/ResourceTypes.cpp;l=1770;drc=d4e49e63519397789d284a03aea5fafc119cb1b0) से भिन्न है, जो `AndroidManifest.xml`, `res/xml/*.xml`, `res/layout/*.xml` आदि के लिए होता है और जिसमें कोई स्पष्ट "मैजिक वैल्यू" नहीं होती, हालाँकि यह आमतौर पर `0300 0800` से शुरू होता है (जो [हेडर](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h;l=608;drc=d4e49e63519397789d284a03aea5fafc119cb1b0) है जिसमें `type=RES_XML_TYPE` और `headerSize=8` होता है)
जब भी सिस्टम इन आंतरिक स्टेट XML फ़ाइलों में से किसी को पढ़ता है, तो वह [Binary XML फ़ाइल के लिए पार्सर या नियमित XML पार्सर चुनने के लिए फ़ाइल में `"ABX\0"` मैजिक वैल्यू का उपयोग करता है](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/util/Xml.java;l=188-192;drc=97a370a95275e79c69e79d7ead11aa38934a5575)। जब भी इन फ़ाइलों को Binary XML के रूप में सहेजा जाता है, यह [सिस्टम प्रॉपर्टी द्वारा नियंत्रित](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/util/Xml.java;drc=97a370a95275e79c69e79d7ead11aa38934a5575;l=74?q=Xml.java) होता है और डिफ़ॉल्ट रूप से सक्षम होता है
जब Binary XML फ़ाइलें उपयोग में होती हैं, तो आप उनकी सामग्री पढ़ सकते हैं, उदाहरण के लिए `adb shell su 0 abx2xml /data/system/packages.xml -` के माध्यम से
इस बाइनरी प्रारूप की एक खासियत यह है कि यह टाइप किए गए एक्सेसर्स प्रदान करता है, इसलिए सीरियलाइज़र `attributeInt(String namespace, String name, int value)` विधि प्रदान करता है, जो मान को बाइनरी इंटीजर के रूप में लिखता है, जिससे String के माध्यम से राउंड-ट्रिप से बचा जा सकता है जो नया आवंटन और उसके बाद गारबेज कलेक्शन के लिए ऑब्जेक्ट होता
एक अन्य प्रकार जिसे सीधे सीरियलाइज़ किया जा सकता है वह बाइट ऐरे है```java
@Override
public XmlSerializer attributeBytesBase64(String namespace, String name, byte[] value)
throws IOException {
if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
mOut.writeByte(ATTRIBUTE | TYPE_BYTES_BASE64);
mOut.writeInternedUTF(name);
mOut.writeShort(value.length);
mOut.write(value);
return this;
}
attributeBytesHex भी ऐसी ही विधि है जो केवल लिखे गए TYPE_* टैग में भिन्न होती है। उस टैग का उपयोग abx2xml टूल द्वारा बाइट ऐरे को उपयुक्त String प्रस्तुति में बदलने के लिए किया जाता है।
mOut FastDataOutput का उदाहरण है, जो Java के DataOutputStream के कार्य प्रदान करता है। writeByte/writeShort/writeInt/writeUTF/write मानक DataOutputStream के समान प्रारूप का उपयोग करते हैं।
Parcel के समान, यदि लेखन/पठन के दौरान कुछ मेल नहीं खाता है तो बाद में पढ़ा गया डेटा गलत ऑफसेट से लिया जाएगा, हालाँकि Parcel के विपरीत, BinaryXmlSerializer/BinaryXmlPullParser के उपयोग में गलतियाँ हमलावर को पढ़े गए डेटा में मनमाने ढंग से छेड़छाड़ करने की क्षमता नहीं देतीं (उस स्थिति में हमलावर नए टैग/विशेषता नाम/मान पेश नहीं कर सकता)।
BinaryXmlSerializer क्लास में या FastDataOutput में गलतियाँ, हालाँकि, ऐसा कर सकती हैं।
उपरोक्त विधि में यदि हम 65536 लंबाई वाला बाइट ऐरे लिखने का प्रयास करें, तो हम writeShort() के साथ लंबाई लिखेंगे, जो प्रभावी रूप से 0 लिखेगा, जिसके बाद वास्तविक ऐरे सामग्री लिखी जाएगी।
उस बेमेल का शोषण करने के लिए, हमें कुछ ऐसी फ़ाइल चुननी होगी जहाँ हम attributeBytesBase64 या attributeBytesHex में मनमाना बाइट ऐरे इंजेक्ट कर सकें, साथ ही उस फ़ाइल का संशोधन हमलावर के लिए मूल्यवान हो।
PackageInstaller क्लास पैकेज को इंस्टॉलेशन के लिए तैयार करने की क्षमता प्रदान करती है। बिना किसी अनुमति की आवश्यकता के, कोई भी ऐप अस्थायी निर्देशिका में इंस्टॉल किए जाने वाले नए APK को लिख सकता है। एक बार इंस्टॉलेशन के लिए आवश्यक सब कुछ लिख दिए जाने के बाद, इंस्टॉल करने वाला ऐप commit() PackageInstaller.Session कर सकता है, जिसका अर्थ है कि वह इंस्टॉलेशन फ़ाइलों में कोई और परिवर्तन नहीं कर पाएगा और Session उपयोगकर्ता अनुमोदन या वास्तविक इंस्टॉलेशन के लिए तैयार है।
इन कार्यों की स्थिति /data/system/install_sessions.xml में संग्रहीत की जाती है। इंस्टॉलर ऐप उदाहरण के लिए अपने PackageInstaller.Session के लिए Package Manager Service द्वारा बनाई गई अस्थायी निर्देशिका में बड़े APK का आधा हिस्सा डाउनलोड कर सकता है, फिर रीबूट के बाद डाउनलोड फिर से शुरू कर सकता है, शेष आधा लिख सकता है और इंस्टॉलेशन commit कर सकता है।
एक संभावना install_sessions.xml में डेटा लिखना है ताकि सत्र को staged के रूप में चिह्नित किया जा सके, जिसका अर्थ है कि यह अगले बूट के बाद इंस्टॉल होगा।