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

فئة OWASP: MASVS-PLATFORM: التفاعل مع النظام الأساسي

نظرة عامة

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

يمكن أيضًا تنفيذ جسر أصلي باستخدام قنوات رسائل HTML باستخدام WebViewCompat.postWebMessage من Android أو WebMessagePort.postMessage للتواصل مع 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 في إعدادات أمان الشبكة config. راجِع مستندات usesCleartextTraffic لمزيد من المعلومات.

Xml

<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، تحقَّق من صحة كل من النظام والمضيف (النطاقات المدرَجة في القائمة المسموح بها). يجب فتح أي نطاقات غير مدرَجة في القائمة المسموح بها باستخدام المتصفح التلقائي بدلاً من ذلك.

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

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

عدم عرض بيانات حساسة

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

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

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

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

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


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

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

الإجراءات المخفِّفة

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


الموارد