वेबव्यू – असुरक्षित यूआरआई लोड हो रहा है

OWASP कैटगरी: MASVS-CODE: कोड की क्वालिटी

खास जानकारी

असुरक्षित यूआरआई लोडिंग तब होती है, जब कोई Android ऐप्लिकेशन किसी यूआरआई को वेबव्यू में लोड करने से पहले, उसकी वैधता का सही तरीके से आकलन नहीं कर पाता.

इस तरह की कमज़ोरी की मुख्य वजह यह है कि यूआरआई में कई हिस्से होते हैं.इनमें से कम से कम स्कीम और होस्ट (अथॉरिटी वाले हिस्से का) की पुष्टि होनी चाहिए. जैसे, यूआरआई को WebView में लोड करने या ऐप्लिकेशन में इसका इस्तेमाल करने से पहले, इसे अनुमति वाली सूची में शामिल किया जाना चाहिए.

आम तौर पर होने वाली गलतियां:

  • इसमें सिर्फ़ होस्ट की जांच की जाती है, न कि स्कीम की. इससे हमलावर, पुष्टि किए गए होस्ट के साथ http://, content:// या javascript:// जैसी स्कीम का इस्तेमाल कर सकता है.
  • यूआरआई को सही तरीके से पार्स न कर पाना. खास तौर पर, उन मामलों में जहां यूआरआई को स्ट्रिंग के तौर पर मिला है.
  • स्कीम की पुष्टि की जा रही है, लेकिन होस्ट की नहीं (होस्ट की पुष्टि नहीं हो रही है).

आखिरी मामले में, ऐसा आम तौर पर तब होता है, जब ऐप्लिकेशन को किसी प्राइमरी डोमेन के मनमुताबिक सबडोमेन की अनुमति देनी होती है. इसलिए, भले ही होस्टनेम को सही तरीके से निकाला गया हो, ऐप्लिकेशन, निकाले गए स्ट्रिंग सेक्शन में प्राइमरी डोमेन की मौजूदगी की पुष्टि करने के लिए, java.lang.String क्लास के startsWith, endsWith, या contains जैसे तरीकों का इस्तेमाल करता है. इन तरीकों का गलत इस्तेमाल करने से, गलत नतीजे मिल सकते हैं. साथ ही, ऐप्लिकेशन को संभावित रूप से नुकसान पहुंचाने वाले होस्ट पर भरोसा करने के लिए मजबूर किया जा सकता है.

असर

होस्ट का इस्तेमाल किस संदर्भ में किया जा रहा है, इसके आधार पर असर अलग-अलग हो सकता है. ऐसे मामलों में जहां वेबव्यू में नुकसान पहुंचाने वाले यूआरआई (यानी कि फ़िल्टरिंग/अनुमति वाली सूची को बायपास करने वाला यूआरआई) को लोड करने से, खाता हैक किया जा सकता है. जैसे, फ़िशिंग का इस्तेमाल करना, कोड लागू करना (जैसे, नुकसान पहुंचाने वाली JavaScript लोड करना) या डिवाइस से समझौता करना (हाइपरलिंक का इस्तेमाल करके डिलीवर किए गए कोड का गलत इस्तेमाल करना).

जोखिम कम करने के तरीके

स्ट्रिंग यूआरआई को हैंडल करते समय, स्ट्रिंग को यूआरआई के तौर पर पार्स करना ज़रूरी है. साथ ही, स्कीम और होस्ट, दोनों की पुष्टि करना भी ज़रूरी है:

Kotlin

fun isUriTrusted(incomingUri: String, trustedHostName: String): Boolean {
    try {
        val uri = Uri.parse(incomingUri)
        return uri.scheme == "https" && uri.host == trustedHostName
    } catch (e: NullPointerException) {
        throw NullPointerException("incomingUri is null or not well-formed")
    }
}

Java

public static boolean isUriTrusted(String incomingUri, String trustedHostName)
    throws NullPointerException {
        try {
            Uri uri = Uri.parse(incomingUri);
            return uri.getScheme().equals("https") &&
            uri.getHost().equals(trustedHostName);
        } catch (NullPointerException e) {
            throw new NullPointerException(
                "incomingUri is null or not well-formed");
        }
    }

होस्ट की पुष्टि करने के लिए, यूआरआई के उस हिस्से को अलग करने के बाद, यह ज़रूरी है कि उसकी पूरी तरह से पुष्टि की जाए. ऐसा इसलिए, ताकि यह पता लगाया जा सके कि होस्ट भरोसेमंद है या नहीं. startsWith या endsWith जैसे तरीकों का इस्तेमाल करना ज़रूरी होने पर, सही सिंटैक्स का इस्तेमाल करना ज़रूरी है. साथ ही, ज़रूरी वर्णों या सिंबल को अनदेखा नहीं करना चाहिए. उदाहरण के लिए, सटीक मिलान के लिए endsWith को डोमेन नाम से पहले "." डॉट वर्ण की ज़रूरत होती है. इन वर्णों को अनदेखा करने से, गलत मिलान हो सकते हैं और सुरक्षा से समझौता हो सकता है. सबडोमेन को कई बार नेस्ट किया जा सकता है. इसलिए, होस्टनेम की पुष्टि करने के लिए रेगुलर एक्सप्रेशन मैचिंग का इस्तेमाल करने का सुझाव नहीं दिया जाता.

योगदान देने वाले लोग: Microsoft Threat Intelligence के दिमित्रियोस वालसमारास और माइकल पेक

संसाधन