アプリ開発やサイト制作のスマホ端末実機検証・テスト-Remote TestKit

Androidアプリセキュリティ〜WebViewの注意点(2)〜

WebViewの機能のひとつであるaddJavascriptInterface()の仕様の危険性についてご紹介します。
前回はWebViewの悪用されやすい仕様とデータ漏えいの危険性の仕組みをご紹介しました。
今回はWebViewの機能のひとつであるaddJavascriptInterface()の仕様の危険性についてご紹介します。

addJavascriptInterface()とは

WebViewにはインターネット上やAndroid端末ローカル上から読み込んだHTMLファイル内のJavaScriptとアプリ内の処理を連携させるためのインタフェースを生成する機能があります。
この連携機能によって、”アプリ内のJava” と ”アプリ外(インターネット上、ローカル上)のJavaScript” がお互いのオブジェクトにアクセスできるようになり、例えば「アプリ内のJavaで処理したデータをWebView内のJavaScriptに渡して画面に表示する」処理や「JavaScriptで表示に使用しているデータを直接Javaメソッドに渡す」処理が可能になります。
Webサーバと連携して処理をすすめるようなアプリでは、毎回リクエスト/レスポンスのパラメータを取得して加工するという処理を省くことができます。

図1. addJavaScriptIntreface()によるJavaScriptとの連携

addJavascriptInterface()の脆弱性の実例

上記のように有用な機能ではありますが、アプリ外部とのブリッジになる機能であるため、いくつかのアプリで脆弱性が公開されています。これまでJVN iPediaで発表された脆弱性には以下のようなものがあります(※1)。

  • サイボウズ KUNAI for Android において任意の Java のメソッドが実行される脆弱性
  • サイボウズLive for Android において任意の Java のメソッドが実行される脆弱性
  • Sleipnir Mobile for Android において任意の Java のメソッドが実行される脆弱性

(2013年8月28日現在 JVN iPediaの検索結果より引用)
(※1) 上記脆弱性はiPediaにはaddJavascriptInterface()が原因であるとは記載されていませんでしたが、アプリベンダーの公式サイト等で詳細が発表されています。
iPediaには上記脆弱性以外にもaddJavascriptInterface()が原因であると推測される脆弱性が見受けられましたが、アプリベンダー等も含めて明確には説明されていないため本稿には記載していません。

一般的なこの脆弱性の解説として「細工されたHTMLファイルを閲覧することで任意の Java のメソッドが実行される」と言われています。
基本的には”公開されている”オブジェクトにしかアクセスできないはずですが、解説には”任意のJavaのメソッドが実行される”とあります。これがどのような仕組みであるのかをご説明します。

addJavascriptInterface()の危険性

まず前提としてアプリ側からJavaScriptのオブジェクトにアクセスすることに危険性はありません。

危険性があるのは、JavaScript側からアプリ内のオブジェクトへアクセスする場合です。つまりWebViewで悪意のあるJavaScriptが埋め込まれたHTMLファイルを閲覧した場合に、JavaScriptからアプリ内のJavaメソッドを実行したり変数にアクセスしたりするケースになります。
このことは、Android DevelopersのaddJavascriptInterface()の説明にIMPORTANTとして以下のように記載されています(※2からの抜粋を意訳)。

addJavascriptInterface()は強力な機能であるがセキュリティリスクも存在する。JavaScriptがリフレクションを使用してpublicフィールドにアクセスできるからだ。信頼できないコンテンツを含む環境においてWebViewでこのメソッドを使用することは、攻撃者にアプリの実行権限内でJavaコードが実行することを許してしまう。使用する際は特別な注意を払うこと。
(※2) WebView | Android Developers

上記ではリフレクションという言葉が使われています。
リフレクションとは実行時にJavaのクラスの様々な情報(クラス名、親クラス名、メソッドの一覧、全フィールドとその属性等)を取得したり、任意のクラスをロードしたり、メソッドを実行したりすることができる機能のことです。
このリフレクション機能によって”任意の”Javaのメソッドが実行されることになります。また、以下のようなことが実行可能になります。

  • java.lang.RuntimeクラスをロードしてOSコマンドの実行やネイティブライブラリのロードが可能
  • contextを取得してSystemServiceを利用し電話番号をはじめ、各種端末情報を取得することが可能(※3)。

(※3)ただしアプリ内からのメソッド実行になるため、そのアプリに付与されているを越えたメソッド実行はできません。
例えば電話番号の取得には<uses-permission android:name=“android.permission.READ_PHONE_STATE” />が必要になります。

このように、アプリから実行できることは全て外部からでも実行できてしまうということになり、非常に危険性が高くなります。

対策

前述のように危険度が高い脆弱性となりうるため、addJavascriptInterface()を使用しない実装にすることを推奨しますが、使用する際の対策として以下のような手法が考えられます。

WebViewの接続先を自身で用意したHTMLファイルのみに限定する

WebViewの接続先は自身で用意したHTMLファイルのみにすることが重要です。接続先がユーザ入力や他アプリから渡される等、アプリ外部から取得したURLである場合は特に危険度が高くなるため、仕様として避けるか、避けられない場合は入力値の検証をすることが重要です。入力値の検証は、アクセス先HTMLファイルが目的のホスト内か、目的のディレクトリ内かどうか等を確認します。以下が一例になります。

public boolean isTargetHost(String accessUrl) {
    //アクセス先ホスト名等。できるだけスコープが小さい方がよい
    String prefix = "https://www.ntt-cert.org/contents/html/";

    //アクセス先URIが上記で指定した文字列で開始されているかどうか
    if (accessUrl.startsWith(prefix)) {
        return true;
    }else {
        return false;
    }
}

HTMLファイルがインターネット上に存在する場合、httpsを使用して接続先が正当なものであるかどうかを検証することも必要です(※4)。

(※4) アプリとJavaScriptの連携がhttpである場合、接続先ホストの正当性を確認する手段がありません。Android端末は外に持ち運び外部のWi-Fi環境に接続する機会も多いため、偽装アクセスポイントに接続してしまったり不正なDNSが稼働している環境に接続してしまったりすることで意図しないホストに接続されてしまうリスクがPC環境より高くなると考えられます。

WebViewでは「証明書が信頼出来る機関から発行されたものかどうか」と「証明書のCN(Common Name)がURLと一致しているかどうか」を自動で確認するようになっています。開発環境等で正規の証明書が使用されていないサーバに接続するために証明書検証を無効にしている場合もあるかと思いますが、検証しない処理のままリリースしないようにすることも重要です。

Android OS 4.2以降で追加されたアノテーションを使用する

OS側でも対策がとられ始めています。

公式ドキュメントには、JELLY_BEANもしくはそれ以下のバージョンでは危険性があるという記載がありますが、これはJELLY_BEAN_MR1(OS 4.2)以降ではアノテーションとして@JavascriptInterfaceが付与されたpublicメソッドのみがJavaScriptから実行可能になっているからです。つまりJavaScript側からは開発者がアプリ内で指定したメソッド以外は呼び出せないようになっています。

    @JavascriptInterface
    public void methodForJS (String str){
        ・・・・・

以下のようにAndroidManifest.xmlのtargetversionでAPIレベル17(OS4.2)を指定することでこの制限を使用することができます。

<uses-sdk android:minSdkVersion="xx"
      android:maxSdkVersion="xx"
      android:targetSdkVersion="17" />

ただし、現時点でOS 4.2を搭載した端末がまだ多く出回っていないこともあり(2013年8月27日現在のAndroid DevelopersのDashboardsによるとシェア6.5%とのことです)、OS 4.2をメインに開発するケースは少ないと思います。Build TargetがOS 4.2未満の開発環境で@JavaScriptInterfaceを使用するとEclipse上でエラーとなりビルドができないため、現実的にこの対策を使用できるのはもう少し時間が必要かなと感じました。

最後に

2回にわたってWebViewを利用する際の注意点をご紹介しました。
WebViewは多くの脆弱性が発見されていることも事実ですが、開発者にとってコード量を圧倒的に減らしてくれる有用な部品です。
使用時にはしっかりと注意点をおさらいし、便利に使いこなしましょう。

執筆者プロフィール 鈴木 崇文、安部 剛

NTT-CERTメンバとして、セキュリティインシデントの対応支援、再発防止策の 検討、トレーニングプログラムの開発およびセ キュリティ関連情報の提供など を実施中。