فئة OWASP: MASVS-STORAGE: مساحة التخزين
نظرة عامة
يتناول هذا المستند عدة مشاكل متعلقة بتضمين الملفات تتشارك في إجراءات التخفيف المشابهة. تتعلّق هذه المشاكل بالثغرات الأمنية الناتجة عن الوصول إلى الملفات داخل مكوّنات WebView، وتتراوح بين WebSettings
الخطير الذي يسمح بالوصول إلى الملفات أو تفعيل JavaScript، وطريقة WebKit التي تنشئ طلب اختيار ملف. سيكون هذا المستند مفيدًا إذا كنت تبحث عن إرشادات حول معالجة المشاكل في WebView الناتجة عن استخدام المخطط file://
، والوصول غير المحدود إلى الملفات المحلية، وهجمات Cross-Site Scripting.
على وجه التحديد، يتناول هذا المستند المواضيع التالية:
-
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. يمكن أن تسمح أذونات الملفات الواسعة النطاق للمهاجمين بالوصول إلى الملفات المحلية وسرقة البيانات الحسّاسة أو معلومات التعريف الشخصية أو بيانات التطبيقات الخاصة. قد يؤدي تفعيل تنفيذ JavaScript إلى السماح للمهاجمين بتشغيل JavaScript داخل WebView أو على جهاز المستخدم. قد تؤدي الملفات التي يتم اختيارها باستخدام طريقة onShowFileChooser
إلى تعريض أمان المستخدم للخطر، إذ لا يمكن للطريقة أو WebView التأكّد من أنّ مصدر الملف موثوق به.
الخطر: الوصول الخطير إلى الملفات من خلال file://
يمكن أن يؤدي تفعيل setAllowFileAccess
وsetAllowFileAccessFromFileURLs
وsetAllowUniversalAccessFromFileURLs
إلى السماح لطلبات WebView وملفات Intent الضارة التي تتضمّن سياق file://
بالوصول إلى ملفات محلية عشوائية، بما في ذلك ملفات تعريف الارتباط في WebView وبيانات التطبيق الخاصة. بالإضافة إلى ذلك، يمكن أن يسمح استخدام طريقة onShowFileChooser
للمستخدمين باختيار الملفات وتنزيلها من مصادر غير موثوق بها.
ويمكن أن تؤدي كل هذه الطرق إلى استخراج معلومات التعريف الشخصية أو بيانات اعتماد تسجيل الدخول أو غيرها من البيانات الحساسة، وذلك حسب إعدادات التطبيق.
إجراءات التخفيف
التحقّق من صحة عناوين URL للملفات
إذا كان تطبيقك يتطلّب الوصول إلى الملفات من خلال عناوين URL file://
، من المهم
إضافة عناوين 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 أو تساويها.
المخاطرة: File-Based XSS
يؤدي ضبط طريقة setJavacriptEnabled
على TRUE
إلى السماح بتنفيذ JavaScript داخل WebView، وعند دمجه مع إذن الوصول إلى الملفات كما هو موضّح سابقًا، يصبح من الممكن تنفيذ هجمات البرمجة النصية على المواقع الإلكترونية (XSS) المستندة إلى الملفات من خلال تنفيذ الرمز البرمجي داخل ملفات عشوائية أو مواقع إلكترونية ضارة يتم فتحها داخل WebView.
إجراءات التخفيف
منع مكوّنات WebView من تحميل الملفات المحلية
كما هو الحال مع المخاطر السابقة، يمكن تجنُّب الثغرة الأمنية File-based 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.
المراجع
- صفحة مرجع واجهة برمجة التطبيقات setAllowUniversalAccessFromFileURLs
- صفحة مرجع واجهة برمجة التطبيقات setAllowFileAccessFromFileURLs
- صفحة مرجع WebViewAssetLoader API
- مستندات CodeQL
- مدونة Oversecured
- صفحة مرجع onShowFileChooser