WebView - 安全でないファイルの包含

OWASP カテゴリ: MASVS-STORAGE: ストレージ

概要

このドキュメントでは、ファイルの包含に関連するいくつかの問題と、それらの問題に対する同様の緩和策について説明します。これらの問題は、WebView 内のファイルへのアクセスに起因する脆弱性に焦点を当てており、ファイル アクセスを許可する危険な WebSettings や JavaScript の有効化から、ファイル選択リクエストを作成する WebKit メソッドまで、さまざまな問題が含まれています。このドキュメントは、file:// スキームの使用、ローカル ファイルへの無制限のアクセス、クロスサイト スクリプティングによって生じる WebView 内の問題の修正に関するガイダンスを探している場合に役立ちます。

具体的には、このドキュメントでは次のトピックについて説明します。

  • WebSettings は、WebView の設定状態を管理するメソッドを含むクラスです。これらの方法では、WebView がさまざまな攻撃を受けやすくなります。後で説明します。このドキュメントでは、ファイルへのアクセス方法と、JavaScript の実行を許可する設定について説明します。
  • setAllowFileAccesssetAllowFileAccessFromFileURLssetAllowUniversalAccessFromFileURLs メソッドを使用すると、ファイル スキーム URL(file://)を使用してローカル ファイルへのアクセス権を付与できます。ただし、悪意のあるスクリプトによって悪用され、アプリがアクセスできる任意のローカル ファイル(独自の /data/ フォルダなど)にアクセスされる可能性があります。そのため、これらのメソッドは安全でないとしてフラグが立てられ、API 30 で非推奨になり、WebViewAssetLoader などのより安全な代替手段に置き換���られました。
  • setJavascriptEnabled メソッドを使用すると、WebView 内での JavaScript の実行を有効にできます。これにより、アプリケーションがファイル ベースの XSS に対して脆弱になります。特に、ローカル ファイルや信頼できないウェブ コンテンツ(実行可能コードが含まれている可能性があるもの)の読み込みを許可するように構成されている場合、外部ソースによって作成または変更される可能性のあるファイルへのアクセスを許可するように構成されている場合、WebView が JavaScript を実行できるように構成されている場合は、ユーザーとそのデータが危険にさらされます。
  • WebChromeClient.onShowFileChooser は、ウェブブラウジング ツールを提供する android.webkit パッケージに属するメソッドです。このメソッドを使用すると、ユーザーが WebView 内でファイルを選択できるようになります。ただし、WebView では選択されるファイルに制限が適用されないため、この機能が不正使用される可能性があります。

影響

ファイルの包含の影響は、WebView で構成されている WebSettings によって異なります。ファイル権限が過度に広範すぎると、攻撃者がローカル ファイルにアクセスし、機密データ、個人情報(PII)、非公開アプリデータを盗む可能性があります。JavaScript の実行を有効にすると、攻撃者が WebView 内またはユーザーのデバイスで JavaScript を実行できる可能性があります。onShowFileChooser メソッドを使用して選択されたファイルは、メソッドまたは WebView がファイルソースが信頼できるかどうかを保証する方法がないため、ユーザーのセキュリティを侵害する可能性があります。

リスク: file:// によるファイルへの危険なアクセス

setAllowFileAccesssetAllowFileAccessFromFileURLssetAllowUniversalAccessFromFileURLs を有効にすると、file:// コンテキストを持つ悪意のあるインテントや WebView リクエストが、WebView Cookie やアプリの非公開データなど、任意のローカル ファイルにアクセスできるようになります。さらに、onShowFileChooser メソッドを使用すると、ユーザーは信頼できないソースからファイルを選択してダウンロードできます。

これらの方法はすべて、アプリケーションの構成によっては、PII、ログイン認証情報、その他の機密データの流出につながる可能性があります。

リスクの軽減

ファイルの URL を検証する

アプリで file:// URL を介してファイルにアクセスする必要がある場合は、よくある間違いを避けるために、正当であることが確認されている特定の URL のみを許可リストに登録することが重要です。

WebViewAssetLoader を使用する

上記のメソッドの代わりに WebViewAssetLoader を使用してください。この方法では、file:// スキームではなく http(s)//: スキームを使用してローカル ファイル システム アセットにアクセスするため、説明した攻撃の影響を受けません。

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() の値は、デフォルトで API レベル 29 以前では TRUE、API レベル 30 以降では FALSE に設定されます。

他の WebSettings を構成する必要がある場合は、特に API レベル 29 以下のアプリの場合は、これらのメソッドを明示的に無効にすることをおすすめします。


リスク: ファイルベースの XSS

setJavacriptEnabled メソッドを TRUE に設定すると、WebView 内で JavaScript を実行できます。また、前述のようにファイル アクセスを有効にすると、任意のファイル内のコードの実行や、WebView 内で開かれた悪意のあるウェブサイトを介して、ファイルベースの XSS が可能になります。

リスクの軽減

WebView がローカル ファイルを読み込まないようにする

前述のリスクと同様に、setAllowFileAccess()setAllowFileAccessFromFileURLs()setAllowUniversalAccessFromFileURLs()FALSE に設定すると、ファイルベースの XSS を回避できます。

WebView が JavaScript を実行しないようにする

WebView 内で JavaScript を実行できないように、メソッド setJavascriptEnabledFALSE に設定します。

WebView で信頼できないコンテンツが読み込まれないようにする

WebView 内でこれらの設定を有効にすることが必要な場合もあります。この場合、信頼できるコンテンツのみが読み込まれるようにすることが重要です。コンテンツの信頼性を保証する方法の一つとして、JavaScript の実行を管理対象のものに限定し、任意の JavaScript を禁止する方法があります。クリアテキスト トラフィックの読み込みを防ぐことで、危険な設定の WebView が HTTP URL を読み込めないようにすることができます。これは、マニフェストで android:usesCleartextTrafficFalse に設定するか、HTTP トラフィックを禁止する Network Security Config を設定することで行えます。


リソース