فئة OWASP: MASVS-CODE: جودة الرمز
نظرة عامة
يحدث تحميل معرّف موارد منتظم (URI) غير آمن عندما يتعذّر على تطبيق Android تقييم صحة معرّف الموارد المنتظم بشكل صحيح قبل تحميله في WebView.
السبب الأساسي وراء هذا النوع من الثغرات الأمنية هو أنّ معرّف الموارد المنتظم يتألف من أجزاء متعددة، يجب التحقّق من نظام معرّف الموارد المنتظم والمضيف (جزء السلطة) على الأقل (مثل إضافتهما إلى القائمة المسموح بها) قبل تحميل معرّف الموارد المنتظم في WebView أو استخدامه داخليًا من قِبل التطبيق.
في ما يلي الأخطاء الأكثر شيوعًا:
- التحقّق من المضيف بدون التحقّق من النظام، ما يسمح للمهاجم باستخدام أنظمة مثل
http://أوcontent://أوjavascript://مع مضيف تم التحقّق منه. - تعذُّر تحليل معرّف الموارد المنتظم بشكل صحيح، خاصةً في الحالات التي يتم فيها تلقّي معرّف الموارد المنتظم كسلسلة.
- التحقّق من النظام بدون التحقّق من المضيف (التحقّق غير الكافي من المضيف)
في ما يتعلق بالحالة الأخيرة، يحدث ذلك عادةً عندما يحتاج التطبيق إلى السماح بنطاقات فرعية عشوائية لنطاق أساسي. حتى إذا تم استخراج اسم المضيف بشكل صحيح، يستخدم التطبيق طرقًا مثل startsWith أو endsWith, أو contains من فئة java.lang.String للتحقّق من وجود نطاق أساسي في قسم السلسلة المستخرَجة. إذا تم استخدام هذه الطرق بشكل غير صحيح، قد تؤدي إلى نتائج خاطئة وتجبر التطبيق على الوثوق بشكل غير صحيح بمضيف قد يكون ضارًا.
التأثير
يمكن أن يختلف التأثير حسب السياق الذي يتم فيه استخدام المضيف. في الحالات التي قد يؤدي فيها تحميل معرّف موارد منتظم ضار (أي معرّف موارد منتظم تجاوز الفلترة أو القائمة المسموح بها) في WebView إلى الاستيلاء على الحساب (مثل استخدام التصيّد الاحتيالي) أو تنفيذ الرمز (مثل تحميل JavaScript ضار) أو اختراق الجهاز (تنفيذ رمز الاستغلال الذي يتم تسليمه باستخدام رابط تشعّبي).
الإجراءات المخفّفة
عند التعامل مع معرّفات الموارد المنتظمة (URI) كسلاسل، من المهم تحليل السلسلة كمعرّف موارد منتظم والتحقّق من النظام والمضيف على حد سواء:
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