WebView: الجسور المدمجة

فئة OWASP: MASVS-PLATFORM: التفاعل مع المنصة

نظرة عامة

الجسر الأصلي، الذي يُعرف أحيانًا باسم جسر JavaScript، هو آلية تُسهِّل التواصل بين WebView ورمز Android الأصلي، ويتم ذلك باستخدام addJavascriptInterface. يتيح ذلك تبادل الرسائل في اتجاهين بين رمز JavaScript الذي يتم تشغيله في WebView ورمز Java لتطبيق Android. تُعرِض الطريقة addJavascriptInterface كائن Java لجميع إطارات WebView، ويمكن لأي إطار الوصول إلى اسم الكائن وتنفيذ الإجراءات عليه. ومع ذلك، لا توجد آلية للتطبيق التحقق من مصدر إطار الاتصال داخل WebView، مما يزيد من مستوى الأمان المخاوف، لأن مصداقية المحتوى تبقى غير مؤكدة.

يمكن أيضًا تنفيذ جسر أصلي باستخدام قنوات رسائل HTML باستخدام WebViewCompat.postWebMessage أو WebMessagePort.postMessage من Android للتواصل مع Window.postMessage من JavaScript. يمكن أن يقبل كلّ من WebViewCompat.postWebMessage و WebMessagePort.postMessage رسائل JavaScript المُرسَلة من خلال Window.postMessage والتي سيتم تنفيذها داخل WebView.

هناك مخاطر متعددة مرتبطة بالجسور الأصلية:

  • الجسور المستندة إلى JavaScriptInterface:
    • تُدخل الطريقة addJavascriptInterface عنصر Java مزوَّدًا في كل إطار من WebView، بما في ذلك إطارات iframe، ما يعني أنّه معرّض للهجوم من قِبل جهات خارجية ضارة تُدخل إطارات في موقع إلكتروني مشروع. إنّ التطبيقات التي تستهدف المستوى 16 لواجهة برمجة التطبيقات أو الإصدارات الأقدم معرّضة بشكل خاص لخطر التعرّض لهجوم، لأنّه يمكن استخدام هذه الطريقة للسماح لـ JavaScript بالتحكّم في التطبيق المضيف.
    • إنّ عرض محتوى غير موثوق به يقدّمه المستخدم في مكوّنات WebView التي تم تفعيل الربط الأصلي فيها يسمح بهجمات النصوص البرمجية على المواقع الإلكترونية (XSS).
  • الجسور المستندة إلى MessageChannel:
    • يعني عدم التحقّق من المصدر في نقاط نهاية قناة الرسائل أنّه سيتم قبول الرسائل من أي مُرسِل، بما في ذلك الرسائل التي تحتوي على رمز ضار.
    • من الممكن أن يتم عن طريق الخطأ تعريض Java لبرنامج JavaScript عشوائي.

التأثير

يمكن أن يستفيد الفاعلون الضارون من الطريقتَين addJavascriptInterface وpostWebMessage وpostMessage للوصول إلى رمز برمجي يتحكّمون فيه أو التلاعب به أو حقنه في WebView. قد يؤدي ذلك إلى إعادة توجيه المستخدمين إلى مواقع ضارّة، أو تحميل محتوى ضار أو تشغيل شفرة ضارة على أجهزتهم استخراج البيانات الحساسة أو تحقيق تصعيد الامتيازات.

الخطر: مخاطر addJavascriptInterface

ينفذ WebView الوظائف الأساسية للمتصفح، مثل عرض الصفحة، والتنقل، وتنفيذ JavaScript. يمكن استخدام WebView داخل تطبيق لعرض محتوى الويب كجزء من تنسيق نشاط. تنفيذ إعلان مدمج مع المحتوى جسر ضمن WebView باستخدام طريقة addJavascriptInterface يمكن أن ينشئوا المشكلات الأمنية مثل البرمجة النصية على مستوى المواقع (XSS)، أو التي تسمح للمهاجمين بتحميل محتوى غير موثوق به من خلال إدخال الواجهة ومعالجة المضيف بطرق غير مقصودة، حيث يتم تنفيذ رمز Java باستخدام أذونات المضيف.

إجراءات التخفيف

إيقاف JavaScript

في الحالات التي لا يتطلب فيها WebView وجود JavaScript، لا تستدعي setJavaScriptEnabled ضمن WebSettings (على سبيل المثال، بينما عرض محتوى HTML ثابت). يتم إيقاف تنفيذ JavaScript تلقائيًا في WebView.

إزالة واجهة JavaScript عند تحميل محتوى غير موثوق به

تأكَّد من إزالة الكائنات من واجهة JavaScript من خلال استدعاء removeJavascriptInterface قبل تحميل المحتوى غير الموثوق به من خلال WebView. على سبيل المثال، يمكن إجراء ذلك في طلب برمجي إلى shouldInterceptRequest.

Kotlin

webView.removeJavascriptInterface("myObject")

Java

webView.removeJavascriptInterface("myObject");

تحميل محتوى الويب عبر HTTPS فقط

إذا كنت بحاجة إلى تحميل محتوى غير موثوق به، تأكَّد من أنّ WebView يحمِّل محتوى الويب من خلال اتصال مشفَّر (اطّلِع أيضًا على إرشاداتنا حول مراسلات النصّ الواضح). منع تنفيذ التحميل الأولي للصفحة على الاتصالات غير المشفَّرة من خلال ضبط android:usesCleartextTraffic على false في ملف AndroidManifest أو منع حركة مرور HTTP في أمان الشبكة . اطّلِع على مستندات usesCleartextTraffic لمزيد من المعلومات. المعلومات.

حجم كبير جدًا

<application
    android:usesCleartextTraffic="false">
    <!-- Other application elements -->
</application>

لضمان عدم حدوث عمليات إعادة توجيه ومزيد من تصفُّح التطبيقات على ملف تعريف الارتباط غير المشفَّر، تحقَّق من مخطّط HTTP في loadUrl أو shouldInterceptRequest:

Kotlin

fun loadSecureUrl(webView: WebView?, url: String?) {
    webView?.let { wv ->  // Ensure valid WebView and URL
        url?.let {
            try {
                val uri = URI(url)
                if (uri.scheme.equals("https", ignoreCase = true)) { // Enforce HTTPS scheme for security
                    wv.loadUrl(url)
                } else {
                    // Log an error or handle the case where the URL is not secure
                    System.err.println("Attempted to load a non-HTTPS URL: $url")
                }
            } catch (e: Exception) {
                // Handle exception for improper URL format
                System.err.println("Invalid URL syntax: $url")
            }
        }
    }
}

Java

public void loadSecureUrl(WebView webView, String url) {
    if (webView != null && url != null) { // Ensure valid WebView and URL
        try {
            URI uri = new URI(url);
            String scheme = uri.getScheme();
            if ("https".equalsIgnoreCase(scheme)) { // Enforce HTTPS scheme for security
                webView.loadUrl(url);
            } else {
                // Log an error or handle the case where the URL is not secure
                System.err.println("Attempted to load a non-HTTPS URL: " + url);
            }
        } catch (URISyntaxException e) {
            // Handle exception for improper URL format
            System.err.println("Invalid URL syntax: " + url);
        }
    }
}

التحقّق من صحة المحتوى غير الموثوق به

إذا تم تحميل أي روابط خارجية في WebView، تحقَّق من أنّ المخطّط والمضيف. (نطاقات القائمة المسموح بها). يجب أن يفتح المتصفّح التلقائي أي نطاقات غير مُدرَجة في القائمة المسموح بها.

عدم تحميل محتوى غير موثوق به

إذا أمكن، حمِّل فقط عناوين URL ذات النطاق الصارم والمحتوى المملوك للتطبيق مطوّر البرامج إلى WebView.

عدم الكشف عن البيانات الحسّاسة

إذا كان تطبيقك يصل إلى البيانات الحسّاسة باستخدام WebView، ننصحك باستخدام أسلوب clearCache لحذف أي ملفات مخزّنة على الجهاز قبل استخدام واجهة JavaScript. يمكنك أيضًا استخدام الرؤوس من جهة الخادم، مثل no-store، لتحديد أنّه لا يجب على التطبيق تخزين محتوى معيّن مؤقتًا.

عدم عرض وظائف حسّاسة

إذا كان تطبيقك يتطلب أذونات حسّاسة أو يجمع بيانات حسّاسة، والتأكد من طلبه من الرمز البرمجي داخل التطبيق وإبراز الإفصاح للمستخدمين. تجنَّب استخدام واجهات JavaScript لأي عمليات حساسة أو بيانات مستخدمين.

استهداف المستوى 21 من واجهة برمجة التطبيقات أو المستويات الأعلى

من الطرق الآمنة لاستخدام طريقة addJavascriptInterface هي استهداف المستوى 21 أو أعلى لواجهة برمجة التطبيقات من خلال التأكّد من عدم استدعاء الطريقة إلا عند التشغيل على المستوى 21 أو أعلى لواجهة برمجة التطبيقات. قبل واجهة برمجة التطبيقات 21، كان بإمكان JavaScript استخدام الانعكاس للوصول إلى واجهة برمجة التطبيقات العامة الخاصة بالكائن الذي تم إدخاله.


المخاطر: مخاطر MessageChannel

يمكن أن يؤدي عدم توفّر عنصر التحكّم في المصدر في postWebMessage() وpostMessage() إلى السماح للمهاجمين باعتراض الرسائل أو إرسال الرسائل إلى معالِجات أصلية.

إجراءات التخفيف

عند إعداد postWebMessage() أو postMessage()، السماح بالرسائل من النطاقات الموثوق بها من خلال تجنب استخدام * كأصل مستهدف، وبدلاً من تحديد نطاق الإرسال المتوقع بشكل صريح.


المراجع