קטגוריה ב-OWASP: MASVS-STORAGE: אחסון
סקירה כללית
במסמך הזה מפורטות כמה בעיות שקשורות להכללת קבצים, שיש להן פתרונות דומים. הבעיות האלה מתמקדות בנקודות חולשה שנובעות מגישה לקבצים ב-WebViews, ומשתנות מ-WebSettings
מסוכן שמאפשר גישה לקבצים או מפעיל JavaScript, ועד לשיטה של WebKit שיוצרת בקשה לבחירת קובץ. המסמך הזה יעזור לכם לפתור בעיות ב-WebView שנובעות משימוש בסכימה file://
, מגישה בלתי מוגבלת לקבצים מקומיים ומ-XSS (Cross-Site Scripting).
באופן ספציפי יותר, במסמך הזה מפורטים הנושאים הבאים:
WebSettings
היא כיתה שמכילה שיטות שמנהלות את מצבי ההגדרה של WebViews. השיטות האלה עלולות לחשוף את WebView למתקפות שונות, שתוארו בהמשך. במסמך הזה נבחן את השיטות שקשורות לאופן הגישה לקובצים, ואת ההגדרה שמאפשרת להריץ JavaScript:- אפשר להשתמש בשיטות
setAllowFileAccess
,setAllowFileAccessFromFileURLs
ו-setAllowUniversalAccessFromFileURLs
כדי להעניק גישה לקבצים מקומיים באמצעות כתובת URL של סכימה של קובץ (file://
). עם זאת, סקריפטים זדוניים עלולים לנצל אותן כדי לגשת לקבצים מקומיים שרירותיים שיש לאפליקציה גישה אליהם, כמו התיקייה/data/
שלהם. לכן, השיטות האלה סומנו כלא מאובטחות והוצאו משימוש ב-API 30 לטובת חלופות בטוחות יותר, כמוWebViewAssetLoader
. - אפשר להשתמש בשיטה
setJavascriptEnabled
כדי להפעיל את ההרצה של JavaScript בתוך רכיבי WebView. כתוצאה מכך, האפליקציות חשופות לפרצת אבטחה מסוג XSS שמבוססת על קבצים. במיוחד כשהגדרתם שהם יאפשרו טעינה של קבצים מקומיים או תוכן אינטרנט לא מהימן שעשוי להכיל קוד שניתן להפעלה, או כשהגדרתם שהם יאפשרו גישה לקבצים שאפשר ליצור או לשנות על ידי מקורות חיצוניים, או כשהגדרתם שרכיבי WebView יוכלו להריץ JavaScript, המשתמשים והנתונים שלהם נמצאים בסיכון. WebChromeClient.onShowFileChooser
היא שיטה ששייכת לחבילהandroid.webkit
, שמספקת כלים לגלישה באינטרנט. אפשר להשתמש בשיטה הזו כדי לאפשר למשתמשים לבחור קבצים ב-WebView. עם זאת, אפשר לנצל לרעה את התכונה הזו כי תצוגות ה-WebView לא אוכפות הגבלות על הקובץ שנבחר.
השפעה
ההשפעה של הכללת הקובץ יכולה להשתנות בהתאם להגדרות WebSettings שמוגדרות ב-WebView. הרשאות קבצים רחבות מדי עלולות לאפשר לתוקפים לגשת לקבצים מקומיים ולגנוב מידע אישי רגיש, פרטים אישיים מזהים (PII) או נתונים פרטיים של אפליקציות. הפעלת JavaScript יכולה לאפשר לתוקפים להריץ JavaScript ב-WebView או במכשיר של משתמש. קבצים שנבחרים באמצעות השיטה onShowFileChooser
עלולים לסכן את אבטחת המשתמשים, כי אין שום דרך להבטיח שהשיטה או רכיב ה-WebView יבטיחו שמקור הקובץ מהימן.
סיכון: גישה מסוכנת לקבצים דרך file://
הפעלת ההרשאות setAllowFileAccess
, setAllowFileAccessFromFileURLs
ו-setAllowUniversalAccessFromFileURLs
עלולה לאפשר לכוונות זדוניות ולבקשות WebView עם הקשר file://
לגשת לקבצים מקומיים שרירותיים, כולל קובצי cookie של 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
ברמת API 29 ומטה, ול-FALSE
ברמת API 30 ואילך.
אם יש צורך להגדיר WebSettings
אחרים, מומלץ להשבית את השיטות האלה באופן מפורש, במיוחד באפליקציות שמטרגטות רמות API שקטנות מ-29 או שוות לה.
סיכון: XSS מבוסס-קובץ
הגדרת השיטה setJavacriptEnabled
ל-TRUE
מאפשרת להריץ JavaScript ב-WebView. בשילוב עם הפעלת הגישה לקובץ כפי שמתואר למעלה, אפשר לבצע XSS מבוסס-קובץ באמצעות הפעלת קוד בקבצים שרירותיים או באתרים זדוניים שנפתחים ב-WebView.
פעולות מיטיגציה
מניעת טעינת קבצים מקומיים ב-WebViews
בדומה לסיכונים הקודמים, אפשר למנוע XSS שמבוסס על קבצים אם ההגדרות של setAllowFileAccess()
, setAllowFileAccessFromFileURLs()
ו-setAllowUniversalAccessFromFileURLs()
מוגדרות כ-FALSE
.
מניעת הפעלת JavaScript ברכיבי WebView
מגדירים את השיטה setJavascriptEnabled
לערך FALSE
כדי שלא ניתן יהיה להריץ JavaScript בתוך רכיבי WebView.
מוודאים שרכיבי WebView לא טוענים תוכן לא מהימן
לפעמים צריך להפעיל את ההגדרות האלה ב-WebViews. במקרה כזה, חשוב לוודא שרק תוכן מהימן נטען. אחת הדרכים הטובות להבטיח שהתוכן מהימן היא להגביל את ההפעלה של JavaScript רק לקוד שאתם שולטים בו ולא לאפשר הפעלה של JavaScript שרירותי. לחלופין, אפשר למנוע את טעינת התנועה בטקסט ללא הצפנה כדי לוודא שרכיבי WebView עם הגדרות מסוכנות לא יוכלו לטעון לפחות כתובות URL מסוג HTTP. אפשר לעשות זאת דרך המניפסט, על ידי הגדרת android:usesCleartextTraffic
לערך False
, או על ידי הגדרת Network Security Config
שאוסרת על תנועת HTTP.
משאבים
- דף העזרה של ה-API של setAllowUniversalAccessFromFileURLs
- דף העזרה של ה-API של setAllowFileAccessFromFileURLs
- דף העזרה של WebViewAssetLoader API
- מסמכי התיעוד של CodeQL
- בלוג עם אבטחה מוגזמת
- דף העזרה של onShowFileChooser