こんにちは!デジタルペンテスト部のbooooomです!今回は私の好奇心だけを満たす内容でごった煮ブログを書かせていただきます!
最近はOWASPが公開したMobile Application Security Testing Guide(以下、MASTG)に基づいてスマートフォンアプリの調査を勉強しています。その中で、どうでもいいことかもしれませんが、どうしても気になることが1つあります…
それはdrozerのことです。気になる理由はなんとなくメンテされていないイメージを持っていて、それでもMASTG記載の調査手順では使われているということからです。調べてみたところ、実は前でMASTGのGithub上でdrozerを代替しないかという提案(?)がIssuesにもなっていました。
最新のMASTGv1.6.0でdrozerが調査手順で使われているのは主に「Determining Whether Sensitive Stored Data Has Been Exposed via IPC Mechanisms」です(英文長っ!)。この章ではContent Providerの利用から生じた情報漏えいの調査を行います。今回のブログはこの章で述べたContent Provider周りの調査をdrozer以外の何かで頑張ってみます!
※内容は私の理解に基づいているため、間違いが含まれている可能性があります。ご注意ください。
drozerとは
Androidアプリケーションの脆弱性調査を(半)自動的に実施してくれるツールです。調査する項目が実行しやすいようにモジュール化されています。 使うためには、drozer-agent-2.3.4.apkアプリをAndroid端末にインストールする必要があります。
MASTGでのContent Provider調査は何をするか
では、まずMASTGで記載されている、drozerを使ったContent Providerの調査を見ましょう。本文を読むことがおすすめですが、(超)簡単にまとめると、以下の3つを確認します。
1. 公開設定、読み取り・書き込みの制限
Content Providerの公開設定、および読み取り・書き込み権限の設定不備によって情報の漏えい・データの改ざんが可能かを確認します。
まずはapp.provider.info
モジュールを使って、Content Providerの公開設定と読み取り・書き込み制限を確認します。Content Providerが公開されていると分かった後scanner.provider.finduris
モジュールを使って、Content ProviderにアクセスするためのURIパスを特定します。実際にContent Providerを介してSQLデータベース内に保存される情報を読み取る場合はapp.provider.query
モジュールを使います。
書き込みができるかは、以下のいずれかのモジュールを使って調査します。しかし、app.provider.delete
を使うことを推奨します。データの追加や更新の際と違って、削除はデータ型等を考えなくても良いからです。
app.provider.delete
app.provider.insert
app.provider.update
※ここで、読み取り・書き込みができるのはreadPermission
とwritePermission
を全く設定しないProviderのみです。
2. SQLインジェクション
scanner.provider.injection
モジュールを使って、調査対象アプリのパッケージ名だけ指定すれば良いです。Content ProviderにSQLインジェクションができるか調べてくれます。
3. ディレクトリトラバーサル
scanner.provider.traversal
モジュールを使います。上記のようにパッケージ名だけ指定すれば良いです。ディレクトリトラバーサルで他のファイルを読み取れるかを調べてくれます。
drozer以外で頑張ってみる!
drozerを使わない場合、Content Providerの調査はどのように行うかを見ましょう。
今回の調査対象アプリはMASTGと同様にsieve.apkを使います。
1. 公開設定、読み取り・書き込みの制限
Content Providerの公開設定、および読み取り・書き込みの制限はAndroidManifest.xml
内にある<provider>
タグから確認できます。<provider>
タグにexported="true"
と設定される、または<intent-filter>
がある場合、そのContent Providerは外部のアプリケーションに公開されています。また、readPermission
とwritePermission
の設定も確認できます。
URIパスの特定はAndroidManifest.xml
内にある<provider>
のauthorities
およびpath
属性から確認できます。また、APKパッケージを展開した後のdex
ファイル内に対して、content://
をキーワードにしてgrepしても良いです。(drozerの公開されているソースコードにもこのような処理があります。)
上記の方法以外、URIパスの特定を動的に実施したい!場合はMedusaを使うこともできます。
Medusaのmedusa.py
MedusaとはdrozerのようにAndroidアプリケーションの調査を(半)自動的に実施してくれるツールです。こちらも、様々な機能がモジュール化されており、また複数のモジュールを同時に使うことができます。frida
ベースですので、medusa.py
を起動させる前にAndroid端末でfrida
サーバを起動させる必要があります。
Medusaはmedusa.py
以外、mango.py
という実行ファイルもあります。個人の感覚的には、medusa.py
は動的解析でmango.py
は静的解析に使うイメージです。
動的解析で、URIパスを特定するためにはcontent_providers/content_provider_query
モジュールを使います。medusa.py
を起動した後に、下記を実行させてください。
medusa > use content_providers/content_provider_query medusa > compile medusa > run -f com.mwr.example.sieve (調査対象アプリのパッケージ名)
medusaをsieve
のプロセスにアタッチした後、Android端末でアプリケーションを操作します。すると、下記のようにContent ProviderのURIパスが表示されます。
URIパスが特定できれば、読み込みは下記のadb
で行うことができます。
書き込みはquery
ではなく、insert
、update
またはdelete
を実行させます。
$ adb shell content query --uri [URIパス]
2. SQLインジェクション
scanner.provider.injection
モジュールのソースコードを抜粋して、下記に示します。57行目と63行目のソースコード通り、テストケースは'
のみです。
adb
を代替にできます。コマンドは以下です。(エスケープ注意!)
3. ディレクトリトラバーサル
scanner.provider.traversal
モジュールも上記と同様です。下記の抜粋したソースコードの53行目がテストケースとなります。
adb
を使って調査する場合は下記のコマンドになります。
$ adb shell content read --uri content://com.mwr.example.sieve.FileBackupProvider/../../../../../../../../etc/hosts
まとめ
手順はより多くなりますが、drozerを使わなくてもContent Providerの調査は可能です!
Content Providerの読み取り・書き込みをするためにはadb
を代替に使用できますので、drozerの機能で便利だな~と思っているのはURIパスを特定するためのscanner.provider.finduris
モジュールです。
しかし、アプローチが異なりますが、同じくURIパスを特定するためにはMedusaを使うこともできます。(drozerでは静的解析、Medusaではメソッドをフックする動的解析)
URIパスの特定についてもう1つ気になることは、今回調査対象のアプリは難読化されていないことです。難読化が実装されている場合はdrozerとmedusaの調査結果が異なるかもしれません...
おまけ-SQLインジェクション調査の別法-
Webサーバに対するSQLインジェクションを調査するために、有名なsqlmapというツールがあります。下記のブログではContent Providerに対するSQLインジェクションを調査するためにsqlmapを工夫して使用していました。具体的にはsqlmapとアプリケーションの間にWebサーバを挟んで、通信を経由していました。発想はすごく面白いので実施してみたいですね!