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