今回のONETOPIヘッドラインの検査結果をSDNAメンバーが確認した結果、大きく3種類の脆弱性があることが分かりました。
それぞれの脆弱性は以下のようなものです。
Androidアプリにおけるアクセス制御の脆弱性とは、ActivityやReceiverといったコンポーネントや、SharedPreference・DBといったファイルシステム上に配置されるファイルを、意図せず第三者からアクセス可能な状態にしてしまう問題です。コンポーネントのアクセス制御に不備がある場合、開発者が意図していないタイミング・用途で、他のアプリからコンポーネントが利用されてしまい、情報漏えいなどの問題が発生する危険性があります。
IPAテクニカルウォッチ『Androidアプリの脆弱性』に関するレポートでも、Androidアプリの脆弱性の7割強が「アクセス制御の不備」に起因すると報告されているように、多くのAndroidアプリに見られる脆弱性です。
Secure Coding Checkerでは、「Activityを作る」や「Broadcastを受信する」などで検出できます。
Androidアプリにおけるログ出力の脆弱性とは、LogクラスのメソッドやSystem.out/errを使って、第三者に公開すべきではないセンシティブな情報をログ出力してしまう問題です。Android 4.0以前のバージョンの端末では、端末内の他アプリが出力されたログデータを読み出せてしまうため、情報漏えいの問題が発生する危険性があります。
Secure Coding Checkerでは、「LogCatにログ出力する」で検出できます。
AndroidアプリにおけるHTTPS通信の脆弱性とは、主にHTTPS通信におけるサーバ証明書の検証不備に起因する問題で、サーバ証明書検証に不備があると中間者攻撃(man-in-the-middle)と呼ばれる手法によって、暗号通信を第三者に盗聴されてしまう危険性があります。
この脆弱性も多くのAndroidアプリに見られる脆弱性で、昨年10月にGoogle Playの人気無料アプリの8%に中間者攻撃の脆弱性があったとの研究結果が報告されています。
Secure Coding Checkerでは、「HTTPSで通信する」や「WebViewを使う」で検出できます。
それでは、ONETOPIヘッドラインで見つかった上記脆弱性について、検査結果を細かく確認し、安全なコードに修正していきたいと思います。
Androidアプリが持つコンポーネントのアクセス制御を正しく機能させる、つまり、他のアプリから意図せずアクセスされないようにするには、AndroidManifest.xmlでコンポーネントの公開設定を適切に設定し、他アプリからのアクセスを制限する必要があります。
一例を挙げると、セキュアコーディングガイドでは、Activityのアクセス制御の設定に際して、Activityの用途を「公開」「非公開」「パートナー限定」「自社限定」に分類し、それぞれの用途に応じてexported属性とintent-filterの定義を表3の通りに組み合わせ使用するよう定めています。
- | exported属性の値 | ||
---|---|---|---|
- | true | false | 無指定 |
intent-filter 定義がある | 公開、パートナー限定 | (使用禁止) | 公開、パートナー限定 |
intent-filter 定義がない | 公開、パートナー限定、自社限定 | 非公開 | 非公開 |
表3 セキュアコーディングガイド4.1.3.1.から引用 |
コンポーネントの公開設定を誤ると、そのコンポーネントが開発者の意図していない用途で他のアプリから利用されたり、致命的な情報漏えいにつながったりします。過去の例を見ると、JVN31860555として報告されている問題などが、アクセス制御の脆弱性が原因で発生した問題です。
ONETOPI ヘッドラインの場合、Activity、Broadcast receiver、Content provider、Serviceのほぼすべてに共通して、他のアプリからの情報参照の可否を設定する「exported属性(値)が正しく設定されていない」と指摘されていました(画面4)。
高間:exportedの設定については、ツールで指摘されるまで頭から抜け落ちていました。ほとんどのコンポーネントで「違反」と判定されていますね。
SDNA:exportedの設定は、アプリ開発者の多くが失念してしまう設定項目です。コンポーネントの公開設定はexported属性だけではなく、Intent filterの有無や、permission属性にも左右され、それらの正しい組み合わせはコンポーネントの用途により異なります。コンポーネントの公開設定はセキュアコーディングガイドを参照しながら慎重に行ってください。
高間:画面では、コンポーネントの用途について、質問の回答が最初から選択されていますが、これはどういうことでしょう?
SDNA:Secure Coding Checkerでは、AndroidManifest.xmlなどの内容に基づいて、開発者が意図していたであろうコンポーネントの用途を推測し、初期回答としてあらかじめ選択した状態にします。正しい用途となっているかを確認しながら、アプリの仕様に関する「質問」項目に順次回答してみてください。Secure Coding Checkerは、質問に回答されるたびにアプリの仕様に則したチェックを行い、判定結果を更新します。
アプリの仕様に関する質問に回答した結果、Activity、Broadcast receiver、Content provider、Serviceで検出された脆弱性は、コンポーネントの公開設定に関するもののみとなりました。
高間さんはONETOPIヘッドラインで使用される全てのコンポーネントについて、公開設定を見直しました。コンポーネントの検出項目で表示されているセキュアコーディングガイドへリンクをクリックすると、ガイドの該当個所が表示されます。膨大なガイドの記述の中から、コンポーネントの公開設定に関連する内容を集中的に学び、コードを修正できるようになっています。
高間:アプリで使用しているBroadcast receiverは、システムが送信しているIntentを受け取るのでintent-filterのみ定義していたのですが、セキュアコーディングガイドによると、exported = “false” と指定しなければ他のアプリが送信するIntentを受信することができてしまうのですね(ガイド4.2.3.1)。
SDNA:はい。セキュアコーディングガイドを通読しただけでは、このようなノウハウを実装時に生かすことがなかなかできません。セキュアコーディングガイドとツールを併用して開発中に繰り返しチェックすることで、セキュリティ問題を未然に防ぎつつ、セキュアコーディングの知識を深められるのではと思います。
高間さんは以下のように、他のアプリから利用されるコンポーネントにはexported = “true” を、利用されるべきでないコンポーネントにはexported = “false” を書き加えました。
<activity android:name=".CategoryActivity" android:label="@string/app_name" android:launchMode="singleTask" android:screenOrientation="portrait" > <receiver android:name=".alarm.AlarmInitReceiver" >
<activity android:name=".CategoryActivity" android:label="@string/app_name" android:launchMode="singleTask" android:screenOrientation="portrait" android:exported="true" > <receiver android:name=".alarm.AlarmInitReceiver" android:exported="false" >
コンポーネントの公開設定を修正すると、以下のように、「違反」と判定されていた項目はすべて「安全」となり、コンポーネントの脆弱性が解消されていることが確認できました(画面5)。
引き続き後編では、Log出力に関する脆弱性の修正手順などを紹介します。
Copyright © ITmedia, Inc. All Rights Reserved.