فئة OWASP: MASVS-STORAGE: التخزين
نظرة عامة
يغطّي هذا المستند عدة مشاكل متعلقة بتضمين الملفات والتي تتشارك في إجراءات مماثلة للتخفيف من حدّتها. تتمحور هذه المشاكل حول الثغرات الأمنية الناتجة عن الوصول إلى
الملفات داخل مكوّنات WebView، وتتراوح بين WebSettings الخطيرة التي تسمح بالوصول إلى الملفات أو تفعِّل JavaScript، إلى طريقة WebKit التي تنشئ طلب اختيار ملف. سيكون هذا المستند مفيدًا إذا كنت تبحث عن إرشادات حول معالجة المشاكل داخل WebView الناتجة عن استخدام المخطط file:// والوصول غير المقيّد إلى الملفات المحلية وإدخال النصوص البرمجية على المواقع الإلكترونية.
على وجه التحديد، يغطّي هذا المستند المواضيع التالية:
WebSettingsهي فئة تحتوي على طرق تدير حالات الإعدادات لمكوّنات WebView. يمكن أن تفتح هذه الطرق مكوّنات WebView على هجمات مختلفة سيتم توضيحها لاحقًا. في هذا المستند، سنلقي نظرة على الطرق المتعلقة بكيفية الوصول إلى الملفات والإعداد الذي يسمح بتنفيذ JavaScript:- يمكن استخدام الطرق
setAllowFileAccessوsetAllowFileAccessFromFileURLsوsetAllowUniversalAccessFromFileURLsلمنح إذن الوصول إلى الملفات المحلية باستخدام عنوان URL لمخطط ملف (file://). ومع ذلك، يمكن أن تستغلّها النصوص البرمجية الضارة للوصول إلى ملفات محلية عشوائية يمكن للتطبيق الوصول إليها، مثل مجلد/data/الخاص به. لهذا السبب، تم وضع علامة على هذه الطرق باعتبارها غير آمنة وتم إيقافها نهائيًا في واجهة برمجة التطبيقات 30 لصالح بدائل أكثر أمانًا، مثلWebViewAssetLoader. - يمكن استخدام الطريقة
setJavascriptEnabledلتفعيل تنفيذ JavaScript داخل مكوّنات WebView. وهذا يجعل التطبيقات معرّضة لخطر إدخال النصوص البرمجية على المواقع الإلكترونية (File-based XSS). خاصةً عند ضبطها للسماح بتحميل الملفات المحلية أو محتوى الويب غير الموثوق به الذي قد يحتوي على رمز قابل للتنفيذ، أو ضبطها للسماح بالوصول إلى الملفات التي يمكن إنشاؤها أو تغييرها من مصادر خارجية، أو السماح لمكوّنات WebView بتنفيذ JavaScript، يصبح المستخدمون وبياناتهم معرّضين للخطر. WebChromeClient.onShowFileChooserهي طريقة تنتمي إلى حزمةandroid.webkitالتي توفّر أدوات لتصفّح الويب. يمكن استخدام هذه الطريقة للسماح للمستخدمين باختيار الملفات داخل WebView. ومع ذلك، يمكن إساءة استخدام هذه الميزة لأنّ مكوّنات WebView لا تفرض قيودًا على الملف الذي يتم اختياره.
التأثير
يمكن أن يعتمد تأثير تضمين الملفات على إعدادات WebSettings التي تم ضبطها في WebView. يمكن أن تسمح أذونات الملفات الواسعة جدًا للمهاجمين بالوصول إلى الملفات المحلية وسرقة البيانات الحساسة أو معلومات تكشف الهوية الشخصية (PII) أو بيانات التطبيق الخاصة. يمكن أن يسمح تفعيل تنفيذ JavaScript للمهاجمين بتشغيل JavaScript داخل WebView أو على جهاز المستخدم. يمكن أن تعرّض الملفات التي يتم اختيارها باستخدام الطريقة onShowFileChooser أمان المستخدم للخطر، لأنّه ليس هناك طريقة للطريقة أو WebView للتأكّد من أنّ مصدر الملف موثوق به.
المخاطرة: الوصول المحفوف بالمخاطر إلى الملفات من خلال file://
يمكن أن يسمح تفعيل setAllowFileAccess وsetAllowFileAccessFromFileURLs و
setAllowUniversalAccessFromFileURLs لطلبات WebView وعناصر Intent الضارة التي تتضمّن سياق file:// بالوصول إلى ملفات محلية عشوائية، بما في ذلك ملفات تعريف الارتباط الخاصة بـ WebView وبيانات التطبيق الخاصة. علاوةً على ذلك، يمكن أن يسمح استخدام الطريقة onShowFileChooser للمستخدمين باختيار الملفات وتنزيلها من مصادر غير موثوق بها.
يمكن أن تؤدي كل هذه الطرق إلى استخراج معلومات تكشف الهوية الشخصية أو بيانات تسجيل الدخول أو غيرها من البيانات الحسّاسة، وذلك حسب إعداد التطبيق.
إجراءات التخفيف من حدّة المخاطر
التحقّق من صحة عناوين 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() تلقائيًا على TRUE في مستوى واجهة برمجة التطبيقات 29 والمستويات الأدنى، وعلى FALSE في مستوى واجهة برمجة التطبيقات 30 والمستويات الأعلى. يتم ضبط الطريقتَين setAllowFileAccessFromFileURLs() وsetAllowUniversalAccessFromFileURLs() تلقائيًا على FALSE في مستوى واجهة برمجة التطبيقات 16 والمستويات الأعلى. (تم تغيير هذه الإعدادات التلقائية في مستوى واجهة برمجة التطبيقات 16 لفرض أمان أكثر صرامة من خلال تقييد الوصول إلى الملفات المحلية من المصدر نفسه، ما يحمي التطبيقات من إمكانية إدخال النصوص البرمجية على المواقع الإلكترونية (XSS) والوصول غير المصرّح به إلى الملفات).
إذا كانت هناك حاجة إلى ضبط WebSettings أخرى، من الأفضل إيقاف هذه الطرق بشكلٍ صريح، خاصةً للتطبيقات التي تستهدف مستويات واجهة برمجة التطبيقات 29 أو أقل.
المخاطرة: إدخال النصوص البرمجية على المواقع الإلكترونية (File-based XSS)
يسمح ضبط الطريقة setJavacriptEnabled على TRUE بتنفيذ JavaScript داخل WebView، وبالإضافة إلى تفعيل الوصول إلى الملفات كما هو موضّح سابقًا، يصبح من الممكن إدخال النصوص البرمجية على المواقع الإلكترونية (File-based XSS) من خلال تنفيذ الرمز البرمجي داخل ملفات عشوائية أو مواقع إلكترونية ضارة يتم فتحها داخل WebView.
إجراءات التخفيف من حدّة المخاطر
منع مكوّنات WebView من تحميل الملفات المحلية
كما هو الحال مع المخاطرة السابقة، يمكن تجنُّب إدخال النصوص البرمجية على المواقع الإلكترونية (File-based XSS) إذا تم ضبط setAllowFileAccess() وsetAllowFileAccessFromFileURLs() وsetAllowUniversalAccessFromFileURLs() على FALSE.
منع مكوّنات WebView من تنفيذ JavaScript
اضبط الطريقة setJavascriptEnabled على FALSE حتى لا يمكن تنفيذ JavaScript داخل مكوّنات WebView.
التأكّد من أنّ مكوّنات WebView لا تحمِّل محتوى غير موثوق به
في بعض الأحيان، يكون تفعيل هذه الإعدادات ضروريًا داخل مكوّنات WebView. في هذه الحالة، من المهم التأكّد من أنّه يتم تحميل المحتوى الموثوق به فقط. إنّ قصر تنفيذ JavaScript على الرمز البرمجي الذي تتحكّم فيه فقط ومنع JavaScript العشوائي هو طريقة جيدة لضمان أنّ المحتوى موثوق به. بخلاف ذلك،
يضمن منع تحميل الزيارات بنص واضح ألا تتمكّن مكوّنات WebView التي تتضمّن
إعدادات خطيرة على الأقل من تحميل عناوين URL لبروتوكول HTTP. ويمكن إجراء ذلك
إما من خلال ملف البيان، من خلال ضبط android:usesCleartextTraffic على
False، أو من خلال ضبط Network Security Config التي تمنع زيارات HTTP.
الموارد
- صفحة مرجع واجهة برمجة التطبيقات setAllowUniversalAccessFromFileURLs
- صفحة مرجع واجهة برمجة التطبيقات setAllowFileAccessFromFileURLs
- صفحة مرجع واجهة برمجة التطبيقات WebViewAssetLoader
- مستندات CodeQL
- مدونة Oversecured
- صفحة مرجع onShowFileChooser