WebViews - تضمين ملف غير آمن

فئة OWASP: MASVS-STORAGE: مساحة التخزين

نظرة عامة

يتناول هذا المستند عدة مشاكل متعلّقة بتضمين الملفات التي تتشارك حلولًا مماثلة للتخفيف من تأثيرها. تركّز هذه المشاكل على الثغرات الأمنية الناتجة عن الوصول إلى الملفات ضمن مكوّنات WebView، وتتراوح بين WebSettings الخطيرة التي تسمح بالوصول إلى الملفات أو تفعيل JavaScript، وطريقة WebKit التي تنشئ طلب تحديد ملف. من المفترض أن يكون هذا المستند مفيدًا إذا كنت تبحث عن إرشادات حول حلّ المشاكل في WebView الناتجة عن استخدام مخطط file:// والوصول غير المحدود إلى الملفات المحلية والنصوص البرمجية على مستوى المواقع الإلكترونية.

على وجه التحديد، يتناول هذا المستند المواضيع التالية:

  • WebSettings هي فئة تحتوي على طرق تدير حالات الإعدادات لWebViews. يمكن أن تفتح هذه الطرق WebViews للتعرّض لهجمات مختلفة سيتم تحديدها لاحقًا. في هذا المستند، سنلقي نظرة على الطرق المتعلّقة بكيفية الوصول إلى الملفات، والإعدادات التي تسمح بتنفيذ JavaScript:
  • يمكن استخدام الإجراءات setAllowFileAccess وsetAllowFileAccessFromFileURLs و setAllowUniversalAccessFromFileURLs لمنح الإذن بالوصول إلى الملفات المحلية باستخدام عنوان URL لنظام ملفات (file://). ومع ذلك، يمكن أن يتم استغلالها من خلال النصوص البرمجية الضارة للوصول إلى ملفات محلية عشوائية يمكن للتطبيق الوصول إليها، مثل مجلد /data/ الخاص به. لهذا السبب، تم وضع علامة على هذه الطرق على أنّها غير آمنة وتم إيقافها نهائيًا في واجهة برمجة التطبيقات 30 لإفساح المجال لبدائل أكثر أمانًا، مثل WebViewAssetLoader.
  • يمكن استخدام الطريقة setJavascriptEnabled لتفعيل تنفيذ JavaScript داخل WebViews. ويؤدي ذلك إلى جعل التطبيقات معرّضة لخطر هجمات إدخال النصوص البرمجية على المواقع الإلكترونية (XSS) المستندة إلى الملفات. ويزيد الخطر على المستخدمين وبياناتهم، خاصةً عند ضبط الإعدادات للسماح بتحميل ملفات محلية أو محتوى ويب غير موثوق به قد يحتوي على رمز قابل للتنفيذ، أو عند ضبط الإعدادات للسماح بالوصول إلى ملفات يمكن إنشاؤها أو تغييرها من خلال مصادر خارجية، أو السماح لمكوّنات WebView بتنفيذ JavaScript.
  • WebChromeClient.onShowFileChooser هي طريقة تنتمي إلى حزمة android.webkit التي تقدّم أدوات تصفُّح الويب. يمكن استخدام هذه الطريقة للسماح للمستخدمين باختيار الملفات داخل WebView. ومع ذلك، يمكن إساءة استخدام هذه الميزة لأنّ WebViews لا تفرض قيودًا على الملف الذي يتم اختياره.

التأثير

يمكن أن يعتمد تأثير تضمين الملف على إعدادات WebSettings التي تم ضبطها في WebView. يمكن أن تسمح أذونات الملفات الواسعة النطاق للمهاجمين بالوصول إلى الملفات المحلية وسرقة البيانات الحسّاسة أو معلومات تحديد الهوية الشخصية (PII) أو بيانات التطبيقات الخاصة. يمكن أن يؤدي تفعيل تنفيذ JavaScript إلى السماح للمهاجمين بتشغيل JavaScript داخل WebView أو على جهاز المستخدم. يمكن أن تؤدي الملفات التي يتم اختيارها باستخدام الطريقة onShowFileChooser إلى اختراق أمان المستخدمين، لأنّه لا توجد طريقة لطريقة أو WebView لضمان أنّ مصدر الملف موثوق به.

الخطر: الوصول الخطير إلى الملفات من خلال file://

يمكن أن يؤدي تفعيل setAllowFileAccess وsetAllowFileAccessFromFileURLs و setAllowUniversalAccessFromFileURLs إلى السماح لطلبات WebView الضارّة وطلبات WebView التي تتضمّن سياق file:// بالوصول إلى ملفات محلية عشوائية، بما في ذلك ملفات تعريف ارتباط WebView والبيانات الخاصة بالتطبيق. بالإضافة إلى ذلك، يمكن أن يؤدي استخدام onShowFileChooser الطريقة إلى السماح للمستخدمين باختيار الملفات وتنزيلها من مصادر غير موثوق بها.

يمكن أن تؤدي كل هذه الطرق إلى استخراج معلومات تحديد الهوية الشخصية أو بيانات اعتماد تسجيل الدخول أو بيانات حساسة أخرى، وذلك استنادًا إلى إعدادات التطبيق.

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

التحقّق من صحة عناوين URL الخاصة بالملفّات

إذا كان تطبيقك يتطلّب الوصول إلى الملفات من خلال file:// عناوين URL، من المهم إدراج عناوين URL معيّنة فقط في القائمة المسموح بها، والتي يُعرف أنّها مشروعة، مع تجنُّب الأخطاء الشائعة.

استخدام WebViewAssetLoader

استخدِم WebViewAssetLoader بدلاً من الطرق المذكورة. تستخدِم هذه الطريقة مخطّط http(s)//: بدلاً من مخطّط file:// للوصول إلى مواد عرض نظامملفه المحلي، وهي ليست عرضة للهجوم الموضّح.

Kotlin

val assetLoader: WebViewAssetLoader = Builder()
  .addPathHandler("/assets/", AssetsPathHandler(this))
  .build()

webView.setWebViewClient(object : WebViewClientCompat() {
  @RequiresApi(21)
  override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest): WebResourceResponse {
    return assetLoader.shouldInterceptRequest(request.url)
  }

  @Suppress("deprecation") // for API < 21
  override fun shouldInterceptRequest(view: WebView?, url: String?): WebResourceResponse {
    return assetLoader.shouldInterceptRequest(Uri.parse(url))
  }
})

val webViewSettings: WebSettings = webView.getSettings()
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.allowFileAccessFromFileURLs = false
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.allowUniversalAccessFromFileURLs = false
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.allowFileAccess = false
webViewSettings.allowContentAccess = false

// Assets are hosted under http(s)://appassets.androidplatform.net/assets/... .
// If the application's assets are in the "main/assets" folder this will read the file
// from "main/assets/www/index.html" and load it as if it were hosted on:
// https://appassets.androidplatform.net/assets/www/index.html
webView.loadUrl("https://appassets.androidplatform.net/assets/www/index.html")

Java

final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
         .addPathHandler("/assets/", new AssetsPathHandler(this))
         .build();

webView.setWebViewClient(new WebViewClientCompat() {
    @Override
    @RequiresApi(21)
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        return assetLoader.shouldInterceptRequest(request.getUrl());
    }

    @Override
    @SuppressWarnings("deprecation") // for API < 21
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        return assetLoader.shouldInterceptRequest(Uri.parse(url));
    }
});

WebSettings webViewSettings = webView.getSettings();
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.setAllowFileAccessFromFileURLs(false);
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.setAllowUniversalAccessFromFileURLs(false);
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.setAllowFileAccess(false);
webViewSettings.setAllowContentAccess(false);

// Assets are hosted under http(s)://appassets.androidplatform.net/assets/... .
// If the application's assets are in the "main/assets" folder this will read the file
// from "main/assets/www/index.html" and load it as if it were hosted on:
// https://appassets.androidplatform.net/assets/www/index.html
webview.loadUrl("https://appassets.androidplatform.net/assets/www/index.html");

إيقاف طرق WebSettings الخطيرة

يتم ضبط قيم الطريقتَين setAllowFileAccess() وsetAllowFileAccessFromFileURLs() وsetAllowUniversalAccessFromFileURLs() تلقائيًا على TRUE في المستوى 29 من واجهة برمجة التطبيقات والمستويات الأقدم، وFALSE في المستوى 30 من واجهة برمجة التطبيقات والمستويات الأحدث.

إذا كنت بحاجة إلى ضبط WebSettings أخرى، من الأفضل إيقاف هذه الطرق صراحةً، خاصةً للتطبيقات التي تستهدف مستويات واجهة برمجة التطبيقات الأقل من 29 أو التي تساويه.


الخطر: هجوم XSS المستنِد إلى الملفات

يؤدي ضبط الأسلوب setJavacriptEnabled على TRUE إلى السماح بتنفيذ JavaScript داخل WebView، بالإضافة إلى تفعيل الوصول إلى الملفات كما هو موضح سابقًا، يمكن تنفيذ هجوم XSS المستند إلى الملفات من خلال تنفيذ الرمز ضمن ملفات عشوائية أو مواقع إلكترونية ضارة يتم فتحها داخل WebView.

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

منع مكوّنات WebView من تحميل الملفات المحلية

كما هو الحال مع الخطر السابق، يمكن تجنُّب هجمات XSS المستندة إلى الملفات إذا تم ضبط setAllowFileAccess() وsetAllowFileAccessFromFileURLs() و setAllowUniversalAccessFromFileURLs() على FALSE.

منع مكوّنات WebView من تنفيذ JavaScript

اضبط الطريقة setJavascriptEnabled على FALSE لكي لا يمكن تنفيذ JavaScript داخل WebViews.

التأكّد من أنّ مكوّنات WebView لا تحمِّل محتوى غير موثوق به

في بعض الأحيان، يكون تفعيل هذه الإعدادات ضروريًا في مكوّنات WebView. في هذه الحالة، من المهم التأكّد من تحميل المحتوى الموثوق به فقط. إنّ حصر تنفيذ JavaScript بما يمكنك التحكّم فيه فقط وعدم السماح بتنفيذ JavaScript عشوائيًا هو إحدى الطرق الجيدة لضمان أنّ المحتوى موثوق به. بخلاف ذلك، يؤدي منع تحميل الزيارات النصية الواضحة إلى التأكّد من أنّ مكوّنات WebView التي تتضمّن إعدادات خطيرة لا يمكنها على الأقل تحميل عناوين URL الخاصة ببروتوكول HTTP. ويمكن إجراء ذلك إما من خلال ملف البيان، أو من خلال ضبط android:usesCleartextTraffic على False، أو من خلال ضبط Network Security Config الذي يمنع الزيارات باستخدام بروتوكول HTTP.


المراجع