OWASP कैटगरी: MASVS-CODE: कोड की क्वालिटी
खास जानकारी
Java ऑब्जेक्ट के ज़्यादा डेटा को सेव या ट्रांसफ़र करते समय, डेटा को पहले क्रमबद्ध करना ज़्यादा फ़ायदेमंद होता है. इसके बाद, डेटा को पाने वाला ऐप्लिकेशन, गतिविधि या सेवा देने वाली कंपनी, डेटा को डीसीरियलाइज़ करती है. सामान्य तौर पर, डेटा को क्रमबद्ध किया जाता है. इसके बाद, उपयोगकर्ता के किसी भी इंटरैक्शन के बिना उसे क्रम से लगाया जाता है. हालांकि, डीसीरियलाइज़ेशन की प्रोसेस और उसके ऑब्जेक्ट के बीच भरोसे के संबंध का गलत इस्तेमाल किया जा सकता है. ऐसा करने वाला कोई दुर्भावनापूर्ण व्यक्ति, उदाहरण के लिए, सीरियलाइज़ किए गए ऑब्जेक्ट को इंटरसेप्ट और उनमें बदलाव कर सकता है. इससे नुकसान पहुंचाने वाला व्यक्ति, डिनायल ऑफ़ सर्विस (DoS), विशेषाधिकार बढ़ाने, और रिमोट कोड एक्ज़ीक्यूशन (आरसीई) जैसे हमले कर सकता है.
Serializable क्लास, सीरियलाइज़ेशन को मैनेज करने का एक सामान्य तरीका है. हालांकि, Android में सीरियलाइज़ेशन को मैनेज करने के लिए अपनी क्लास है. इसे Parcel कहा जाता है. Parcel क्लास का इस्तेमाल करके, ऑब्जेक्ट डेटा को बाइट स्ट्रीम डेटा में क्रम से लगाया जा सकता है. साथ ही, Parcelable इंटरफ़ेस का इस्तेमाल करके, इसे Parcel में पैक किया जा सकता है.
इससे Parcel को बेहतर तरीके से ट्रांसपोर्ट या स्टोर किया जा सकता है.
हालांकि, Parcel
class का इस्तेमाल करते समय सावधानी बरतनी चाहिए. इसका मकसद, आईपीसी ट्रांसपोर्ट मैकेनिज़्म को ज़्यादा असरदार बनाना है. हालांकि, इसका इस्तेमाल लोकल परसिस्टेंट स्टोरेज में क्रम से लगाए गए ऑब्जेक्ट को सेव करने के लिए नहीं किया जाना चाहिए. ऐसा करने से, डेटा के साथ काम न करने से जुड़ी समस्याएं हो सकती हैं या डेटा का नुकसान हो सकता है. डेटा को पढ़ने की ज़रूरत होने पर, Parcelable इंटरफ़ेस का इस्तेमाल करके Parcel को डिसिरियलाइज़ किया जा सकता है. साथ ही, इसे वापस ऑब्जेक्ट डेटा में बदला जा सकता है.
Android में डिसिरियलाइज़ेशन का गलत इस्तेमाल करने के तीन मुख्य तरीके हैं:
- डेवलपर की इस गलत धारणा का फ़ायदा उठाना कि कस्टम क्लास टाइप से मिलने वाले ऑब्जेक्ट को डीसीरियलाइज़ करना सुरक्षित है. असल में, किसी भी क्लास से सोर्स किए गए किसी भी ऑब्जेक्ट को नुकसान पहुंचाने वाले कॉन्टेंट से बदला जा सकता है. इससे सबसे खराब स्थिति में, उसी या अन्य ऐप्लिकेशन के क्लास लोडर में रुकावट आ सकती है. इस तरह के छेड़छाड़ में, खतरनाक वैल्यू डाली जाती हैं. क्लास के मकसद के हिसाब से, इससे डेटा चोरी हो सकता है या खाता हैक किया जा सकता है.
- डीसीरियलाइज़ेशन के ऐसे तरीकों का इस्तेमाल करना जिन्हें डिज़ाइन के हिसाब से असुरक्षित माना जाता है. उदाहरण के लिए, CVE-2023-35669, यह स्थानीय विशेषाधिकार बढ़ाने से जुड़ी एक गड़बड़ी है. इसकी वजह से, डीप-लिंक डीसीरियलाइज़ेशन वेक्टर के ज़रिए मनमाना JavaScript कोड इंजेक्ट किया जा सकता है
- ऐप्लिकेशन लॉजिक में मौजूद कमियों का फ़ायदा उठाना. उदाहरण के लिए, CVE-2023-20963, स्थानीय स्तर पर खास सुविधाओं के गलत इस्तेमाल से जुड़ी एक ऐसी समस्या है जिसकी वजह से कोई ऐप्लिकेशन, खास सुविधाओं वाले एनवायरमेंट में कोड डाउनलोड और एक्ज़ीक्यूट कर सकता है. ऐसा Android के WorkSource पार्सल लॉजिक में मौजूद गड़बड़ी की वजह से होता है.
असर
भरोसेमंद न होने या नुकसान पहुंचाने वाले सीरियल किए गए डेटा को डीसीरियलाइज़ करने वाला कोई भी ऐप्लिकेशन, रिमोट कोड प्रोग्राम चलाए जाने या सेवा से इनकार किए जाने के हमलों का शिकार हो सकता है.
जोखिम: भरोसेमंद न होने वाले इनपुट को डीसीरियलाइज़ करना
कोई हमलावर, ऐप्लिकेशन के लॉजिक में पार्सल की पुष्टि न होने की समस्या का फ़ायदा उठा सकता है. ऐसा करके, वह ऐसे ऑब्जेक्ट इंजेक्ट कर सकता है जिन्हें डीसीरियलाइज़ करने के बाद, ऐप्लिकेशन को नुकसान पहुंचाने वाला कोड चलाने के लिए मजबूर किया जा सकता है. इससे सेवा से इनकार (DoS), विशेषाधिकार में बढ़ोतरी, और रिमोट कोड एक्ज़ीक्यूशन (आरसीई) हो सकता है.
इस तरह के हमले, बहुत कम समय में किए जा सकते हैं. उदाहरण के लिए, किसी ऐप्लिकेशन में ऐसा इंटेंट हो सकता है जिसमें सिर्फ़ एक पैरामीटर की ज़रूरत हो. पुष्टि हो जाने के बाद, इसे डिसिरियलाइज़ कर दिया जाएगा. अगर हमलावर, अनुमानित पैरामीटर के साथ-साथ दूसरा, अनचाहा और नुकसान पहुंचाने वाला अतिरिक्त पैरामीटर भेजता है, तो इससे इंजेक्ट किए गए सभी डेटा ऑब्जेक्ट को डिसिरियलाइज़ किया जाएगा. ऐसा इसलिए होगा, क्योंकि इंटेंट, अतिरिक्त पैरामीटर को Bundle के तौर पर मानता है. नुकसान पहुंचाने वाला कोई व्यक्ति इस व्यवहार का इस्तेमाल करके, ऑब्जेक्ट डेटा को इंजेक्ट कर सकता है. इस डेटा को डीसीरियलाइज़ करने पर, आरसीई, डेटा से छेड़छाड़ या डेटा का नुकसान हो सकता है.
जोखिम कम करने के तरीके
सबसे सही तरीका यह है कि सभी क्रमबद्ध डेटा को अविश्वसनीय और संभावित रूप से खतरनाक माना जाए. सीरियलाइज़ किए गए डेटा के रखरखाव के लिए, डेटा की पुष्टि करें. इससे यह पक्का किया जा सकेगा कि डेटा, ऐप्लिकेशन के हिसाब से सही क्लास और फ़ॉर्मैट में है.
java.io.ObjectInputStream लाइब्रेरी के लिए, लुक-अहेड पैटर्न लागू करना एक सही समाधान हो सकता है. डीसीरियलाइज़ेशन के लिए ज़िम्मेदार कोड में बदलाव करके, यह पक्का किया जा सकता है कि इंटेंट में सिर्फ़ साफ़ तौर पर तय की गई क्लास का सेट डीसीरियलाइज़ किया गया हो.
Android 13 (एपीआई लेवल 33) के बाद से, Intent क्लास में कई तरीकों को अपडेट किया गया है. ये पार्सल को हैंडल करने के लिए, पुराने और अब इस्तेमाल नहीं किए जा रहे तरीकों के मुकाबले ज़्यादा सुरक्षित माने जाते हैं. टाइप-सेफ़र के इन नए तरीकों, जैसे कि getParcelableExtra(java.lang.String, java.lang.Class) और getParcelableArrayListExtra(java.lang.String, java.lang.Class) से डेटा टाइप की जांच की जाती है. इससे, टाइप न मिलने की उन कमियों का पता चलता है जिनकी वजह से ऐप्लिकेशन क्रैश हो सकते हैं. साथ ही, इनका इस्तेमाल प्रिविलेज एस्कलेशन के हमलों को अंजाम देने के लिए किया जा सकता है. जैसे, CVE-2021-0928.
यहां दिए गए उदाहरण में, Parcel क्लास के सुरक्षित वर्शन को लागू करने का तरीका बताया गया है:
मान लें कि क्लास UserParcelable, Parcelable को लागू करती है और उपयोगकर्ता के डेटा का एक इंस्टेंस बनाती है. इसके बाद, इसे Parcel में लिखा जाता है. इसके बाद, सीरियलाइज़ किए गए पार्सल को पढ़ने के लिए, readParcelable के इस टाइप-सेफ़र तरीके का इस्तेमाल किया जा सकता है:
Kotlin
val parcel = Parcel.obtain()
val userParcelable = parcel.readParcelable(UserParcelable::class.java.classLoader)
Java
Parcel parcel = Parcel.obtain();
UserParcelable userParcelable = parcel.readParcelable(UserParcelable.class, UserParcelable.CREATOR);
ऊपर दिए गए Java के उदाहरण में, ध्यान दें कि UserParcelable.CREATOR का इस्तेमाल, मेथड में किया गया है. यह ज़रूरी पैरामीटर, readParcelable तरीके को बताता है कि किस तरह के डेटा की उम्मीद की जा रही है. साथ ही, यह readParcelable तरीके के अब इस्तेमाल नहीं किए जा रहे वर्शन से ज़्यादा बेहतर तरीके से काम करता है.
खास जोखिम
इस सेक्शन में उन जोखिमों के बारे में जानकारी दी जाती है जिनके लिए, जोखिम कम करने की सामान्य रणनीतियों के अलावा अन्य रणनीतियों की ज़रूरत होती है. इसके अलावा, इसमें उन जोखिमों के बारे में भी जानकारी दी जाती है जिन्हें एसडीके के किसी लेवल पर कम किया गया था और यहां पूरी जानकारी देने के लिए मौजूद हैं.
जोखिम: अनचाहे ऑब्जेक्ट को डिसिरियलाइज़ करना
किसी क्लास में Serializable इंटरफ़ेस लागू करने से, दी गई क्लास के सभी सबटाइप में इंटरफ़ेस अपने-आप लागू हो जाएगा. इस स्थिति में, कुछ ऑब्जेक्ट ऊपर बताए गए इंटरफ़ेस को इनहेरिट कर सकते हैं. इसका मतलब है कि जिन ऑब्जेक्ट को डिसिरियलाइज़ नहीं किया जाना चाहिए उन्हें भी प्रोसेस किया जाएगा.
इससे अनजाने में हमले की गुंजाइश बढ़ सकती है.
जोखिम कम करने के तरीके
अगर कोई क्लास, Serializable इंटरफ़ेस को इनहेरिट करती है, तो OWASP के दिशा-निर्देशों के मुताबिक, readObject तरीके को इस तरह लागू किया जाना चाहिए, ताकि क्लास में मौजूद ऑब्जेक्ट के सेट को डीसीरियलाइज़ न किया जा सके:
Kotlin
@Throws(IOException::class)
private final fun readObject(in: ObjectInputStream) {
throw IOException("Cannot be deserialized")
}
Java
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
संसाधन
- Parcelables
- पार्सल
- Serializable
- मकसद
- Android में डीसीरियलाइज़ेशन की कमज़ोरियां: एक संक्षिप्त इतिहास
- Android Parcels: The Bad, the Good and the Better (वीडियो)
- Android Parcels: The Bad, the Good and the Better (presentation slides)
- CVE-2014-7911: Android <5.0 में ObjectInputStream का इस्तेमाल करके, विशेषाधिकारों को बढ़ाना
- CVE-CVE-2017-0412
- CVE-2021-0928: पार्सल सीरियलाइज़ेशन/डीसिरियलाइज़ेशन में अंतर
- OWASP के दिशा-निर्देश