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 を設定することで行えます。


リソース