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:// を介したファイルへの危険なアクセス

setAllowFileAccesssetAllowFileAccessFromFileURLs、および setAllowUniversalAccessFromFileURLs を有効にすると、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 が実行されないようにする

メソッド setJavascriptEnabledFALSE に設定すると、WebView 内で JavaScript を実行できなくなります。

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

WebView 内でこれらの設定を有効にする必要がある場合があります。この場合は、信頼できるコンテンツのみが読み込まれるようにすることが重要です。JavaScript の実行を制御するもののみに制限し、任意の JavaScript を許可しないようにすると、コンテンツの信頼性を確保できます。それ以外の場合は、 クリアテキスト トラフィックが読み込まれないようにすることで、 危険な設定を含む WebView が HTTP URL を読み込まないようにします。これは、 マニフェストで android:usesCleartextTrafficFalse に設定するか、HTTP トラフィックを許可しない Network Security Config を設定することで実現できます。


リソース