本サイトは、快適にご利用いただくためにクッキー(Cookie)を使用しております。
Cookieの使用に同意いただける場合は「同意する」ボタンを押してください。
なお本サイトのCookie使用については、「個人情報保護方針」をご覧ください。

最新情報

2022.03.23

Androidアプリの静的テイント解析(FlowDroidを使ったICC分析の実施例)

本稿ではAndroidアプリケーションの静的テイント解析ツール「FlowDroid」のICC分析機能を紹介します。
「テイント解析?
ICC分析? 知らない単語ばかりだなぁ。」と思った方も、大丈夫です。それらの用語は本文で説明します(ただしAndroidアプリの基本的な知識があると、より理解しやすいと思います)。
Androidアプリをテイント解析できるとうたっているツールはいくつかありますが、ICC分析まで出来るものはなかなかありません。アプリを解析するうえで大変強力な機能であるICC分析ですが、今一つ知られていないのも事実です。本稿ではFlowDroidを使って、テストアプリのICC分析を追体験していただきます。さらに、現在も研究/開発途上にあるFlowDroidの現時点での課題もいくつか挙げました。本稿がこれからICC分析を試そうとする方々の一助になれば幸いです。

1.FlowDroidとは

1.1. 用語解説

  FlowDroidの説明をする前に、用語を2つ説明します。

 1.1.1. 静的解析(static analysis)

静的解析(static analysis)とは、ソフトウエアを実行することなく、ソースコードやバイナリファイルを解析することです。逆に、ソフトウエアを実行しながら解析する手法を動的解析(dynamic analysis)と呼びます。

 1.1.2.テイント解析(taint analysis)

テイント解析(taint analysis)とは、アプリ外からアプリ内に入ってくるデータは”tainted”(汚染されている)と見做して印をつけ、そのデータのアプリ内でのフローを追跡し、脆弱性の検知につなげようとする解析手法です。或るデータの"tainted"という印は、そのデータを代入された別の変数やそのデータを引数に取る関数の返り値に次々と伝播していきます。さらにテイント解析では、アプリ内で発生した重要情報(端末の電話番号や位置情報等)がアプリ外に出ていくところも追跡し、情報漏洩の検知を目指します。

情報がアプリ外から入ってきたり、アプリ内で生成されたりする個所をソース(つまり情報源)と呼び、逆に情報がアプリ内で使用されたりアプリ外に出て行ったりする個所をシンク(情報の到達点)と呼びます。テイント解析とは、ソース(情報源)からシンク(情報の到達点)までのデータフローを解析すること、と言えます。静的解析でも動的解析でも使われる解析手法です。

Fig1-2.png

Fig.1 :テイント解析の基本的なイメージ

実際にはもっと難しいこともしています。

Fig2.png

Fig.2 :もう少し複雑なテイント解析のイメージ
(出典:https://blogs.uni-paderborn.de/sse/tools/flowdroid/

変数bのメンバb.ffoo関数の中で、source関数(情報源)によってtaintedラベルが付きます(Fig.2①)。よって、sink関数(情報の到達点)で出力される段階でtaintedなデータフロー(Fig.2⑦)として検出されます。

1.2. FlowDroidとは

FlowDroidは、Androidアプリの静的テイント解析ツールです。単体のプログラムではなく、複数のツールの総称と言った方が良いかもしれません。apk (Android Application Package) を直接解析するため、アプリのソースコードは不要です。AndroidManifest.xmlには無いReceiver(すなわちregisterReceiverで動的に登録されるコンポーネント)も見つけ出し、解析対象に含めます。以下のGithubで公開されています。
https://github.com/secure-software-engineering/FlowDroid

FlowDroidの歴史は古く、2013年の以下の論文が初出ではないかと思われます。
Highly Precise Taint Analysis for Android Application(C.Fritz et al. May 2013)
同時期にバージョン1.0Githubに公開され、以来おもにダルムシュタット工科大学の研究者らが中心となって研究・開発が続けられてきました。

2. ICC分析とは

ICCは Inter Component Communication(コンポーネント間通信)の略です。1つのAndroidアプリは通常、複数のコンポーネントが協調して動作します。データは1つのコンポーネントから別のコンポーネントにジャンプして、渡っていきます。
つまり、あるコンポーネント内のソース(情報源)で出現したtaintedデータは、シンク(情報の到達点)に至るまでの間に、別のコンポーネントを次々経由してゆきます。よって、Androidアプリをテイント解析するには、複数のコンポーネント間でのデータのやり取りを解析する必要があります。

ICC分析の必要性は古くから認識されていたものの、コンポーネントを次々ジャンプしていくデータの追跡は難しく、可能になるには時間がかかりました2015年にiccTA[2]が発表されて注目を集め、FlowDroidには2018年に取り入れられたようです。ICC分析が可能になったことは、Androidアプリのテイント解析において1つのブレークスルーとなりました。

3. 実施例

FlowDroidは本来Javaのライブラリとして利用するものですが、簡単に試せるようコマンドラインツールがついています。今回はそれを使用します。

FlowDroidICC分析を始めるにあたって、まずつまずくのは”ICC modelファイルの作成方法ではないかと思います。ICC modelファイルはアプリ全体のコンポーネントを洗い出し、それらがやり取りするデータ(Intent)についての情報等も併せて記述したファイルです。FlowDroidICC分析するには、事前にこのICC modelファイルを作成し、FlowDroidに渡す必要があります。しかしICC modelファイルの作り方は、FlowDroidのサイトにも、helpにも載っていません。

今回は以下のic3を使用しました。
https://github.com/JordanSamhi/ic3

 3.1. 事前の注意

2021/11/10現在、上記URLic3は、以下の図のように「Use legacy android.support.libraries」にチェックを入れないで作成したアプリには対応していません(作者に対応依頼中)。 今回作成したテストアプリは以下の環境でビルドしました。
 ・OS: Windows10
 ・IDE: Android Studio Arctic Fox | 2020.3.1 Patch 3
 ・Gradle: 7.0.2 (Android Gradle Plugin 7.0.3)
 ・Build-tool: 31.0.0、compileSdkVersion 31、minSdkVersion 16、targetSdkVersion 31

アプリ新規作成時の設定で「Use legacy android.support.libraries」にチェックを入れます。

Fig3.png

Fig.3 :Android Studio2020.3.1でアプリを新規作成する際の設定画面

DroidBenchと呼ばれるベンチマーク用のapkが下記で公開されています(ただし作成されたのは7年以上前です)。
https://github.com/secure-software-engineering/DroidBench/tree/iccta/apk

 3.2. テストアプリの概要

今回作成したテストアプリには2件の脆弱性が含まれています。これらをFlowDroidで検知できるか、確認していきます。

testapp.png

Fig.4: テストアプリの概念図

  3.2.1. 脆弱性①

脆弱性①は、情報(電話番号)の送信先が明示されていないため、不正なアプリに受け取られる可能性がある脆弱性です。

vul1.png

Fig.5: 脆弱性①の概念図

  3.2.2. 脆弱性②

脆弱性②は、アプリ外から受け取った任意のURLをWebViewで表示してしまうため、フィッシングの可能性がある脆弱性です。

vul2.png

Fig.6: 脆弱性②の概念図

 3.3. 作業手順

以下はWindows10で実施した手順です。大まかな流れは以下の通りです。
procedure.png

  3.3.1. 必要なファイルの準備

ic3: https://github.com/JordanSamhi/ic3
FlowDroid: https://github.com/secure-software-engineering/FlowDroid/releases/download/v2.9/soot-infoflow-cmd-2.9.0-jar-with-dependencies.jar
FlowDroidSourcesAndSinks.txt: https://github.com/secure-software-engineering/FlowDroid/blob/develop/soot-infoflow-android/SourcesAndSinks.txt

ic3READMEに従ってビルドし、FlowDroidRelease v2.9をそのまま使用しました(FlowDroidv2.9より前のバージョンにはXXE脆弱性があるとの報告があります)。

SourcesAndSinks.txtに、ソース関数やシンク関数を自由に追加できます。そのままでもたくさんのソース関数とシンク関数が登録されていますが、足りない分は事前に追加しておきます。今回は以下の4行をファイル末尾に追加しました。

<android.webkit.WebView: void loadUrl(java.lang.String)> -> _SINK_
<android.webkit.WebView: void loadDataWithBaseURL(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String)> -> _SINK_
<android.webkit.WebView: void loadData(java.lang.String,java.lang.String,java.lang.String)> -> _SINK_
<android.webkit.WebView: void postUrl(java.lang.String,byte[])> -> _SINK_

今回のテストではWebView関連のシンク関数4つを追加。

  3.3.2. コマンド実行

1.Javaのデフォルトバージョンを8に設定
2.Ic3を実行してICC modelファイルを作成

$ cd <ic3-0.2.1-full.jarが含まれているディレクトリ>
$ java -jar ic3-0.2.1-full.jar -cp <Android Sdk内のplatformsディレクトリを指定> -apk <apkを指定> -protobuf < ICC modelファイルの出力先ディレクトリを指定>

実行例) $ java -jar ic3-0.2.1-full.jar \
-cp C:\Users\<username>\AppData\Local\Android\Sdk\platforms\
-apk C:\Users\<username>\Apks\test_simple\test_simple.apk \
-protobuf C:\Users\<username>\Apks\test_simple\ic3ed

指定した出力先ディレクトリに<パッケージ名>_1.txtというような名前でICC modelファイルが作成されます。

3.FlowDroidを実行

$ cd <soot-infoflow-cmd-2.9.0-jar-with-dependencies.jarが含まれているディレクトリ>
$ java -jar soot-infoflow-cmd-2.9.0-jar-with-dependencies.jar -s <ソースとシンクAPIの一覧ファイルを指定> -p <Android Sdk内のplatformsディレクトリを指定> -a <apkを指定> -im <上記2.で取得したICC modelファイルを指定> -o <結果ファイルの出力先ディレクトリを指定> -ol -on -pr FAST

実行例)$ java -jar soot-infoflow-cmd-2.9.0-jar-with-dependencies.jar \
-s SourcesAndSinks.txt \
-p C:\Users\<username>\AppData\Local\Android\Sdk\platforms \
-a C:\Users\<username>\Apks\test_simple\test_simple.apk \
-im C:\Users\<username>\Apks\test_simple\ic3ed\com.example.test_simple_1.txt \
-o C:\Users\<username>\Apks\test_simple\flowdroid_w_im -ol -on -pr FAST

指定した出力先ディレクトリに<apk>.xmlというような名前で結果ファイルが作成されます。

 3.4. 結果

3.2 テストアプリの概要」で示した2件の脆弱性が、結果ファイルで検出されました。その様子を見てみましょう。以下、結果ファイルを見やすく抜粋しています。

  3.4.1. 脆弱性①の検出

シンク①で出ていくデータの情報源がソース①であることが示されています。

result1_1.pngFlowDroidの結果ファイル抜粋①

上記だけでは明示的なコンポーネント呼び出しか、暗黙的な呼び出しかはわかりませんが、ICC modelファイル(下記)を見ると、Activity2からsendBroadcastでコンポーネントを呼び出す際、暗黙的に呼び出されていることがわかります。

icc_result1.pngICC modeファイル抜粋

  3.4.2. 脆弱性②の検出

シンク②で出ていくデータの情報源がソース②であることが示されています。

result2_1.pngFlowDroidの結果ファイル抜粋②

4. 現時点の長所と課題

 4.1. 長所

  4.1.1 ソースコード不要

apkをそのまま分析します。

  4.1.2 FlowDroidは現在も開発継続中

研究用のPoCとして一時的に作られたものではなく、研究/実運用の両方に役立つことを目標に掲げ、開発が継続中です。他の研究の土台として使われたり、研究成果の比較対象として引用されたりすることも多く、静的テイント解析のスタンダードとなっています。

 4.2 課題

  4.2.1 ソースやシンクが完全に網羅しきれない

Android のAPIは数十万個あるともいわれており、それらのうちどれがソースまたはシンクに該当し、どれが該当しないのか、手動で分類するのも大変ですし、一旦分類できたとしても、Androidのバージョンが変わるたびに追加されたり無くなったりします。よって、ソースやシンクを網羅するのは大変難しい問題です。これはICC分析に限らず、FlowDroid自体の課題です。

この難題を解決するため、機械学習を使った”SuSi”という研究が2014年に発表されましたが、現時点で問題解決には至っていないようです。

<android.location.Location: double getLatitude()> -> _SOURCE_
<android.location.Location: double getLongitude()> -> _SOURCE_
<android.location.LocationManager: android.location.Location getLastKnownLocation(java.lang.String)> -> _SOURCE_
<org.apache.http.HttpResponse: org.apache.http.HttpEntity getEntity()> -> _SOURCE_
<org.apache.http.util.EntityUtils: java.lang.String toString(org.apache.http.HttpEntity)> -> _SOURCE_
<com.google.auth.oauth2.DefaultCredentialsProvider: com.google.auth.oauth2.GoogleCredentials getDefaultCredentials(com.google.api.client.http.HttpTransport)> -> _SOURCE_

中略

<android.app.Activity: void startActivity(android.content.Intent)> -> _SINK_
<android.app.Activity: void startActivity(android.content.Intent,android.os.Bundle)> -> _SINK_
<android.app.Activity: void startActivities(android.content.Intent[])> -> _SINK_
<android.app.Activity: void startActivities(android.content.Intent[],android.os.Bundle)> -> _SINK_
<android.app.Activity: void startActivityForResult(android.content.Intent,int)> -> _SINK_
<android.app.Activity: void startActivityForResult(android.content.Intent,int,android.os.Bundle)> -> _SINK_
<android.app.Activity: void startActivityFromChild(android.app.Activity,android.content.Intent,int,android.os.Bundle)> -> _SINK_

Listing 1: FlowDroidに付随しているソースとシンクAPI一覧ファイル(SourcesAndSinks.txt)の一部抜粋

  4.2.2 オーバーテインティング(Overtainting)

本来taintedでないデータにもtaintedラベルを付けてしまう問題(つまりFalse Positive)です。

FlowDroidに限らず、テイント解析の宿命ともいえる問題です。taintedのラベル付けを精緻に実行しようとすると大変なリソースを消費します。実際の解析ではどこかで現実と折り合いをつけなければなりません。
オーバーテインティングとは逆に、taintedラベルを付けるべきデータにラベルが付かない問題(つまりFalse Negative)をアンダーテインティング(Undertainting)といいます。これら相反する問題を常に抱えながら、両方のバランスを考えた実装をするしかないのです。

FlowDroidではアクセスパスの長さを指定できるようになっていて、その長さを超えるフローは切り捨て、不明な箇所はtaintedのラベルを付けるようになっています。(実際はもう少し複雑です。参考文献[1] Section5 5.4.1参照。)

overtaint.png

Fig.7: オーバーテインティングの例
(ソース部分 出典:” Static data flow analysis for android applications. Technische Universität; 2017 Arzt S.”)

さらに脆弱性検知の観点から、以下の問題があることも明らかです。
例えば「3.実施例」で作ったテストアプリのソース②で、任意のURLがloadUrl()の引数として渡る場合、以下の2通りの渡り方が考えられます。
 i) loadUrl(任意のURL) → WebViewで任意のURLをそのまま表示。すなわちフィッシングなどの脆弱性
 ii) loadUrl(“http://信頼できるサーバ/?badurl=” + 任意のURL) → 信頼できるサーバに引数として文字列が送信されるだけ。脆弱性ではない。
上記ii)は脆弱性ではないため、結果ファイルに出力されると邪魔になり、本当に見るべき脆弱性に注目することが難しくなります。
データフロー解析だけでは余分な情報まで多数出力されるため、その結果をさらに丁寧に確認する別の仕組みが必要です。

  4.2.3 その他の課題
4.2.3.1 Javaでない部分(Cのライブラリ等)は解析できない

FlowDroidは、dalvikバイトコードの解析にsoot(https://github.com/soot-oss/soot)を使っています。よってsootで解析できない領域はFlowDroidでも解析できません。

4.2.3.2 最新のビルド環境への対応

ic3がAndroidXに未対応である点(「3.1 事前の準備」参照)を指しています。

4.2.3.3 結果が見にくい

筆者の主観です。

5 関連する研究

最後にFlowDroidまたはAndroidの静的解析に関連した面白い論文をいくつか挙げてみます。

■ FastDroid…FlowDroid自体の解析手法の改善を試みた論文。
 J.Zhang et al. “FastDroid: Efficient Taint Analysis for Android Application.”(Aug. 2019)
■ B-droid, ConDySTA…FlowDroidと、動的解析やfuzzingといった他の手法を組み合わせることで分析の効果を高めようという論文。
 R.ALmotairy et al. “B-droid: A Static Taint Analysis Framework for Android Applications”(2021)
 X.Zhang et al. “ConDySTA: Context-Aware Dynamic Supplement to Static Taint Analysis”(2021)
■ WebVSec…FlowDroidを土台に、WebView実行時の脆弱性が検知できる、と主張している論文。
 Mohamed A. El-Zawawy et al. “Vulnerabilities in Android webview objects: Still not the end!”(Oct. 2021)
■ StoryDroid… アプリを静的解析し、自動的にUIの遷移図を構成しようという論文。大変面白いのですが、activityのcoverageは平均すると80%前後程度の由。これ自体はセキュリティを目的にしたものではありませんが、これをアプリのセキュリティ向上に生かそうという論文も出ています。
 Sen Chen, et al. "StoryDroid: Automated Generation of Storyboard for Android Apps"(Feb. 2019)
   簡単な説明サイトがあります。https://sites.google.com/view/storydroid/

storydroid.png

(出典:https://arxiv.org/pdf/1902.00476.pdf

■ RAICC… ICC分析の改善を試みた論文。
 J.Samhi, et al. “RAICC: Revealing Atypical Inter-Component Communication in Android Apps”(ICSE 2021)

6 結び

本稿では、ICC分析の力を追体験していただくとともに、現時点の課題も幾つか挙げました。
脆弱性の自動検知は、まだまだ課題山積ですが、多くの研究者が日夜取り組んでいるエネルギッシュな分野でもあります。
今後も引き続き研究の進展に注目していきたいと思います。

7 参考文献

[1]S. Arzt “Static Data Flow Analysis for Android Applications”(2017)
https://tuprints.ulb.tu-darmstadt.de/5937/

[2]Li Li et al. “IccTA: Detecting Inter-Component Privacy Leaks in Android Apps”(2015)
https://cs.uwaterloo.ca/~m2nagapp/courses/CS846/1189/papers/li_icse15.pdf

プロフェッショナルサービス事業部
診断サービス(ソース)チーム

おすすめ記事