AndroidManifestのandroid:exportedに関して 指定がなかったら常にデフォルトでandroid:exported="false"になるわけではないという話。
結論
exported属性は、明示的に全て指定したほうが安全
理由
意図せず外部アプリに公開してる可能性があるため
1.Activityのexportedは無指定の場合、intent-filterの定義の有無によりtrue/falseが決まる。
- intent-filterの定義有:android:exported="true" (外部アプリに公開)
- intent-filterの定義無:android:exported="false" (外部アプリに非公開)
うっかりexportedを無指定でintent-filterを定義してしまうと、
そのactivityは、外部のアプリからでも起動できてしまう。
さらには、そのactivityを起動しようと投げた暗黙的インテントは、外部のアプリも受け取れてしまう。
2.Providerのexportedのデフォルトは、OSバージョンで振る舞いが異なる。
- Android 4.2(API Level 17)までは、デフォルトでtrue
- Android 4.3(API Level 18)からは、デフォルトでfalse
うっかりexportedを無指定でminSdkVersionを17以下も含めていると
OSバージョンの違いで公開/非公開が変わることに。
AndroidManifest.xml見れなきゃ問題ない気もするけど。。。
Google PlayにあるアプリのAndroidManifest.xmlを見てみる。
*【この括弧内は、可変です】
-
Android端末にAndroidManifestを見たいアプリをインストールしておく
-
アプリのパッケージ名をGooglePlayから確認
アプリのページのURLで確認できる
https://play.google.com/store/apps/details?id=【target package name】
-
adbコマンドでフルパスを確認
>adb shell pm list packages -f 【target package name】
package:/data/app/【target package name】-1/base.apk=【target package name】
- adbを使ってapkをPCにpull
> adb pull /data/app/【target package name】-1
-
zipとして展開
-
zip内のAndroidManifest.xmlをAXMLPrinter2.jarで変換
AXMLPrinter2.jar
>java -jar AXMLPrinter2.jar AndroidManifest.xml > AndroidManifestConverted.xml
-
変換後のandroid.intent.category.LAUNCHER以外の<activity>要素で、
exported="true"のactivity、または、exportedの記載がなくintent-filterが定義されているactivityを探す。
体感、評価が低めのアプリに見つかりやすい気がする -
他のアプリから呼んでみる
val targetPackageName : String = "【target package name】"
val targetActivityName : String = "【target activity name】"
val intent : Intent = Intent()
intent.setClassName( targetPackageName, targetActivityName )
startActivity( intent )
こちらでも可
adb am start -n 【target package name】/.【target activity name】
すると普通にactivityが立ち上がってくる
このactivityが、同一パッケージの特定の処理によってのみ、呼び出されることが前提だったりすると、
想定している処理をすっ飛ばして、動作する可能性もある。
まとめ
知識としてはここ見れば書いてある Android アプリのセキュア設計・セキュアコーディングガイド
実際、全部レビューでチェックするのは現実的ではないし、抜け漏れが出るのでツールを使うのが現実的
作るアプリによってセキュリティ面にかけられる金額は全然違うだろうけれど