WebView – Thêm tệp không an toàn

Danh mục OWASP: MASVS-STORAGE: Bộ nhớ

Tổng quan

Tài liệu này đề cập đến một số vấn đề liên quan đến việc đưa tệp vào có các biện pháp giảm thiểu tương tự. Những vấn đề này tập trung vào các lỗ hổng phát sinh từ quyền truy cập vào các tệp trong WebView, từ WebSettings nguy hiểm cho phép truy cập vào tệp hoặc bật JavaScript, đến một phương thức WebKit tạo yêu cầu lựa chọn tệp. Tài liệu này sẽ hữu ích nếu bạn đang tìm hướng dẫn về cách khắc phục các vấn đề trong WebView phát sinh từ việc sử dụng giao thức file://, quyền truy cập không hạn chế vào tệp cục bộ và tập lệnh trên nhiều trang web.

Cụ thể hơn, tài liệu này đề cập đến các chủ đề sau:

  • WebSettings là một lớp chứa các phương thức quản lý trạng thái cài đặt cho WebView. Các phương thức này có thể mở WebView cho nhiều cuộc tấn công khác nhau sẽ được nêu ở phần sau. Trong tài liệu này, chúng ta sẽ xem xét các phương thức liên quan đến cách truy cập vào tệp và chế độ cài đặt cho phép thực thi JavaScript:
  • Bạn có thể sử dụng các phương thức setAllowFileAccess, setAllowFileAccessFromFileURLssetAllowUniversalAccessFromFileURLs để cấp quyền truy cập vào các tệp cục bộ bằng cách sử dụng URL giao thức tệp (file://). Tuy nhiên, các tập lệnh độc hại có thể khai thác các phương thức này để truy cập vào các tệp cục bộ tuỳ ý mà ứng dụng có quyền truy cập, chẳng hạn như thư mục /data/ của chính các tập lệnh đó. Vì lý do này, các phương thức này đã bị gắn cờ là không an toàn và không còn được dùng trong API 30 nữa mà thay vào đó là các phương thức thay thế an toàn hơn, chẳng hạn như WebViewAssetLoader.
  • Bạn có thể sử dụng phương thức setJavascriptEnabled để bật tính năng thực thi JavaScript trong WebView. Điều này khiến các ứng dụng dễ bị tấn công qua XSS dựa trên tệp. Đặc biệt là khi được định cấu hình để cho phép tải tệp cục bộ hoặc nội dung web không đáng tin cậy có thể chứa mã có thể thực thi, được định cấu hình để cho phép truy cập vào các tệp có thể được tạo hoặc thay đổi bởi các nguồn bên ngoài hoặc cho phép WebView thực thi JavaScript, người dùng và dữ liệu của họ sẽ gặp rủi ro.
  • WebChromeClient.onShowFileChooser là một phương thức thuộc gói android.webkit, cung cấp các công cụ duyệt web. Bạn có thể sử dụng phương thức này để cho phép người dùng chọn tệp trong WebView. Tuy nhiên, tính năng này có thể bị lợi dụng vì WebView không thực thi các quy định hạn chế về tệp được chọn.

Tác động

Mức độ tác động của việc đưa tệp vào có thể phụ thuộc vào WebSettings được định cấu hình trong WebView. Quyền truy cập quá rộng vào tệp có thể cho phép kẻ tấn công truy cập vào các tệp cục bộ và đánh cắp dữ liệu nhạy cảm, PII (Thông tin nhận dạng cá nhân) hoặc dữ liệu ứng dụng riêng tư. Việc bật tính năng thực thi JavaScript có thể cho phép kẻ tấn công chạy JavaScript trong WebView hoặc trên thiết bị của người dùng. Các tệp được chọn bằng phương thức onShowFileChooser có thể làm tổn hại đến sự an toàn của người dùng vì không có cách nào để phương thức hoặc WebView đảm bảo rằng nguồn tệp là đáng tin cậy.

Rủi ro: Quyền truy cập gây rủi ro vào tệp thông qua file://

Việc bật setAllowFileAccess, setAllowFileAccessFromFileURLssetAllowUniversalAccessFromFileURLs có thể cho phép các ý định độc hại và yêu cầu WebView có ngữ cảnh file:// truy cập vào các tệp cục bộ tuỳ ý, bao gồm cả cookie WebView và dữ liệu riêng tư của ứng dụng. Ngoài ra, việc sử dụng phương thức onShowFileChooser có thể cho phép người dùng chọn và tải tệp xuống từ các nguồn không đáng tin cậy.

Tất cả các phương thức này đều có thể dẫn đến việc đánh cắp PII, thông tin đăng nhập hoặc dữ liệu nhạy cảm khác, tuỳ thuộc vào cấu hình ứng dụng.

Giải pháp giảm thiểu

Xác thực URL tệp

Nếu ứng dụng của bạn yêu cầu quyền truy cập vào các tệp thông qua URL file://, điều quan trọng là chỉ đưa vào danh sách cho phép những URL cụ thể đã biết là hợp lệ, tránh các lỗi phổ biến.

Sử dụng WebViewAssetLoader

Sử dụng WebViewAssetLoader thay vì các phương thức được đề cập. Phương thức này sử dụng lược đồ http(s)//: thay vì lược đồ file:// để truy cập vào các tài sản hệ thống tệp cục bộ và không dễ bị tấn công như mô tả.

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");

Tắt các phương thức WebSettings nguy hiểm

Theo mặc định, các giá trị của phương thức setAllowFileAccess(), setAllowFileAccessFromFileURLs()setAllowUniversalAccessFromFileURLs() được đặt thành TRUE trong API cấp 29 trở xuống và FALSE trong API cấp 30 trở lên.

Nếu cần định cấu hình WebSettings khác, tốt nhất bạn nên rõ ràng tắt các phương thức này, đặc biệt là đối với các ứng dụng nhắm đến các cấp độ API nhỏ hơn hoặc bằng 29.


Rủi ro: XSS dựa trên tệp

Việc đặt phương thức setJavacriptEnabled thành TRUE cho phép thực thi JavaScript trong WebView, và kết hợp với quyền truy cập tệp được bật như đã nêu trước đó, XSS dựa trên tệp có thể xảy ra thông qua việc thực thi mã trong các tệp tuỳ ý hoặc trang web độc hại được mở trong WebView.

Giải pháp giảm thiểu

Ngăn WebView tải tệp cục bộ

Cũng như rủi ro trước đó, bạn có thể tránh được XSS dựa trên tệp nếu đặt setAllowFileAccess(), setAllowFileAccessFromFileURLs()setAllowUniversalAccessFromFileURLs() thành FALSE.

Ngăn WebView thực thi JavaScript

Đặt phương thức setJavascriptEnabled thành FALSE để không thể thực thi JavaScript trong WebView.

Đảm bảo WebView không tải nội dung không đáng tin cậy

Đôi khi, bạn cần bật các chế độ cài đặt này trong WebView. Trong trường hợp này, điều quan trọng là bạn phải đảm bảo rằng chỉ tải nội dung đáng tin cậy. Việc chỉ cho phép thực thi JavaScript mà bạn kiểm soát và không cho phép JavaScript tuỳ ý là một cách hay để đảm bảo nội dung đáng tin cậy. Nếu không, việc ngăn tải lưu lượng truy cập văn bản thô sẽ đảm bảo rằng WebView có chế độ cài đặt nguy hiểm ít nhất cũng không thể tải URL HTTP. Bạn có thể thực hiện việc này thông qua tệp kê khai, đặt android:usesCleartextTraffic thành False hoặc đặt Network Security Config để không cho phép lưu lượng truy cập HTTP.


Tài nguyên