- Android 14(API v34)は、システムCA証明書を
/systemではなくAPEXベースのcom.android.conscryptモジュールから読み込むように変更し、root権限で証明書を注入していた従来のデバッグフローを壊した
- Android 7 Nougat以降、アプリのデフォルト信頼ストアがシステムCAとユーザーCAに分かれたことで、開発・テスト・リバースエンジニアリング用ツールはシステムCAディレクトリを直接変更する方式に依存してきた
- 新しい構造により、CA証明書はGoogle Play System Updateで更新できるようになり、問題のあるCAの削除や新しいCAの配布を迅速に行える一方、デバイス所有者の制御権は弱まる
- Android 14ベータのエミュレータでは、
/system/etc/security/cacerts、/system/etc/security/cacerts_google、/apex/com.android.conscrypt/cacertsなどをtmpfsで上書きまたは削除しても、Settingsやアプリは引き続きGoogleのCA一覧を参照した
- 執筆時点では、Android 13を維持するか、APEXを使わないカスタムOSが現実的な代替策だったが、その後の更新ではAndroid 14で証明書注入を回避する方法が複数見つかったと述べている
AndroidのCA管理が変わってきた流れ
- Androidは2007年のOpen Handset Alliance発表時、「open platform」「complete access to handset capabilities and tools」といった表現で開放性を強調していた
- 時間が経つにつれ、ユーザー・開発者・研究者が自分の端末を制御できる範囲は徐々に狭まってきたと評価されている
-
Android 7 Nougatでの転換
- デバイス所有者が変更できていたCA一覧がシステムCAとユーザーCAに分離された
- OSベンダーが提供する固定のシステムCA一覧は、すべてのアプリのデフォルトになった
- ユーザーが変更できるCA一覧は、アプリが明示的にopt-inした場合にのみ使われる
- その結果、ほぼすべてのアプリがユーザーCAをデフォルトでは信頼しなくなった
CA証明書が重要な理由
- 端末の信頼済みCAは、暗号化されたネットワークトラフィックの安全性を保証する組織の一覧である
- CAはHTTPSなどのTLS接続で使われる証明書を任意のドメインに発行でき、そのCAを信頼する端末は、その証明書を正当な接続の証拠として受け入れる
- ユーザー自身が作成したCAを端末に信頼させると、自分のHTTPSまたはTLSトラフィックを傍受して確認できる
- スマートフォンが送受信するデータを確認できる
- 必要に応じて変更やブロックもできる
- こうした制御は、セキュリティ・プライバシー研究、リバースエンジニアリング、アプリのデバッグ・テスト、企業内ネットワーク設定、デフォルトCAを信頼しないユーザーにとって重要である
- 非技術ユーザーが誤ってCAを変更しにくくしたり、ユーザーの知らないうちに変更されないよう防いだりするのは合理的だが、高度なユーザーの制御権まで制限すると多くのユースケースが難しくなる
Android 7以降のrootベース回避手法
- Android 7以降も、root権限を得た端末ではシステムCAストアを直接操作できた
- 代表的な方法は、
/system/etc/security/cacerts/に信頼させたい証明書を配置することだった
/systemはroot化端末でも通常は読み取り専用のため、2つの方法が使われていた
/systemディレクトリを書き込み可能に再構成し、再起動後に実際のシステム証明書ディレクトリを修正する
- 読み取り専用ディレクトリの上に一時的な読み書き可能ファイルシステムをマウントし、既存CAをコピーしたうえで新しい証明書を追加する
- 証明書をシステムに受け入れさせるには、ファイル名、権限、SELinuxラベルなどの条件も満たす必要があった
- HTTP Toolkitは、一時マウントベースの手順を自動化し、root化Android端末やエミュレータでワンクリックのインターセプト設定を提供してきた
- このアプローチは、カスタムroot端末、特殊なAndroidディストリビューション、Google公式エミュレータイメージの大半で動作していた
- 一般的なOEM端末と同様にロックされた完全な“Google Play”エディションのイメージは例外である
- mitmproxyの設定ドキュメント、多くのブログ記事、StackOverflowの回答、フォーラム投稿、Magiskパッケージ、cacert.orgの案内でも同様の方式が使われていた
Android 14の新しいCA更新構造
- Android 14は、記事執筆時点では最終ベータ段階で、数週間以内にリリース予定だった
- 主要なセキュリティ機能の1つがリモート更新可能なCA証明書である
- CA証明書管理はコアOSイメージから切り離され、Google Play経由で配布・更新される別コンポーネントへ移された
- この構造により、Googleは問題のあるCAへの信頼をより迅速に取り消せる
- 各スマートフォンベンダーがOS全体のOTAアップデートを配布するまで待つ必要が減る
- Google Play System UpdateだけでAndroid 14以降の端末のCA一覧を変更できる
- デフォルトの信頼済みCAは強い権限を持つため、監督と制裁が必要であり、問題を起こしたCAの権限は迅速に剥奪されるべきである
- 例として、2023年1月にはTrustCorがマルウェア配布組織および米国の防衛・情報契約企業との密接な関係が見つかった後、Googleを含む主要な主体からCAとしての信頼を失った
- 逆に、新しいCAの配布が遅れても問題が生じる
- Let’s Encryptは、古いAndroid端末が最新のルートCAを持っていないため、署名チェーン改善の展開を何度も遅らせなければならなかった
- CA更新の応答性を高める構造自体には価値があるが、Android 14の実装はシステムCAの変更を事実上難しくしている
実際のファイル位置とAPEXの動作
- Android 14の中核的な変更は、従来の
/system/etc/security/cacertsではなく、/apex/com.android.conscrypt/cacertsが存在する場合はそちらから証明書を読み込む点である
/apexはAndroid Pony EXpress、すなわちAPEXコンテナがマウントされるパスである
- APEXモジュールは独立して更新可能なシステムコンポーネントであり、署名付きの不変コンテナとして配布される
- Android 14のCA証明書は、Androidの中核TLS/SSLライブラリである
com.android.conscryptモジュールの一部になった
- APEXの低レベル動作は十分に文書化されておらず、一部の重要な詳細リンクはGoogle内部サイトにしかないとされる
- テストの結果、APEXモジュールの内容は個々のプロセスに直接公開される形になっており、別の場所のファイルを変更してもアプリが見る内容には反映されない挙動を示した
Android 14エミュレータで確認された現象
- Android 14ベータの公式エミュレータにあるAOSPおよび“Play Services”イメージはrootアクセスが可能である
- “Google Play”イメージは一般的なOEM端末のようにロックされている
- API 34の“Google APIs”イメージでエミュレータを作成し、rootシェルを開ける
- 従来の一時マウント方式で次のパスをtmpfsで上書きしても、期待した効果は得られなかった
/system/etc/security/cacerts
/system/etc/security/cacerts_google
/apex/com.android.conscrypt/cacerts
/apex/com.android.conscrypt@340818022/cacerts
- Settings → Security & Privacy → More → Encryption → Trusted Credentialsの“System”タブには、隠したはずの証明書がそのまま表示された
- 例として、“ACCV”証明書ファイル
3c9a4d3b.0をファイルシステム全体で検索すると、マウントで隠している間は見えなかったが、Settingsには引き続き表示された
- 同じ手順をAndroid 13イメージで実行すると、Settingsの証明書一覧は空になり、従来方式が想定どおり動作する
システムイメージを直接変更しても失敗
- Android 14エミュレータを
-writable-systemで起動し、adb root、adb remount、avbctl disable-verification、再起動などを経ると書き込み可能にできる
- その後、
/system/etc/security/cacerts/*、/system/etc/security/cacerts_google/*の証明書は削除できた
- しかし、
/apexの証明書は削除できなかった
- remount後も読み取り専用のままだった
mount -o remount,rw ...コマンドも失敗した
- 実行可能な最も近い操作は、該当する証明書パスを
umountしてmount出力に表示されなくする程度だった
- それでもSettingsの“Trusted”一覧にはCA証明書が引き続き読み込まれた
- これはSettingsアプリのキャッシュ問題ではなく、アプリが参照する証明書ストアの観点でも同じ現象と判断された
- ファイルシステムをどう変更しても、アプリはGoogleのCA一覧を見続けることが分かった
影響と制限
- Android 14では、従来方式でシステムCA証明書をインストールし、デバッグ、リバースエンジニアリング、テスト、研究に使うフローが壊れる
- 執筆時点での代替策は、Android 13を維持するか、CA証明書管理にAPEXモジュールを使わないカスタムOSリリースを利用することだった
- 時間が経つにつれて、Androidメインラインの中核内部コンポーネントと乖離したり、古いソフトウェアを使い続けたりする必要があるため、こうした代替策の実用性は次第に低下する可能性がある
- APEXモジュール内の内容がroot権限でも変更不可能なら、今後APEXへ移されるシステムコンポーネントごとにユーザーの制御権がさらに減る可能性がある
- GrapheneOS、LineageOSのようなAndroidフォークや、Magiskおよび各種モジュールにも問題となりうる
- ただし冒頭の更新によれば、その後の議論と回避策の研究を通じて、Android 14でも証明書注入を可能にする複数の解決法が見つかっている
- Android 14でHTTPSトラフィックをデバッグするには、従来のrootベースのシステムCA注入だけを前提にするのは難しい
1件のコメント
Hacker News の意見
昔の Android の root ツールや、現代的な汎用カスタム ROM、さまざまな Android OS 関連作業をしてきた立場から見ると、このタイトルは今も今後も間違っていると思う
Android における root とは実際に root 権限のことで、望むことは何でもできる [1]
現在の Android root である Magisk は Java コードまで「修正」する機能を含んでいるので、どれだけ深く隠されていてもアクセスできるはず
筆者ができなかったからといって不可能なわけではなく、zygote が CA をキャッシュしていて
stop;startで再起動する必要があるとか、コマンド実行前に正しいマウント名前空間へ切り替える必要がある、といった問題である可能性が高いGrapheneOS と LineageOS はソースコード全体にアクセスできるので望むように変更できるし、制約があるとすれば Google がものすごい速度で壊していくものに追随するのが面倒、という程度
Android がますますユーザー、とくにパワーユーザーに敵対的になっていく中で、もっと多くの人がカスタム ROM に移ってくれることを願っている
夢の中では、セキュリティモデルの第一行が「ユーザーは敵だ」ではなく「OwnerDroid」のような Android フォークを作っているが、小さなレンガをいくつか作っただけで、プロジェクト全体には膨大な作業量が必要
[1] 一部のカーネルレベルの保護は例外だが、GKI がそのリスクを下げてくれる
今はそれができなくなった
もちろんソースコード全体があれば何でも可能で、こうしたモジュールを無効化した Android システムイメージをゼロからビルドすることもできるし、GrapheneOS/LineageOS も対応できる
しかし新しい作業が大量に発生し、コアコンポーネントで Android の実装と分岐すれば、今後さらに多くの保守が必要になる可能性がある
影響を受ける大多数のユーザーにとって、「まずシステムイメージを自分でビルドしろ」というのは、快適に対応できる範囲や時間投資の水準をはるかに超えている
結局ほかの解決策は出てくるだろうが、名前空間に潜り込んで対象プロセスのマウントを個別に変更する、Android が信頼する形で独自の APEX モジュールをビルド・インストールしてシステムモジュールを置き換える、あるいは Frida で個別アプリにフックする、といった形になるだろう
それでも、ユーザーが自分のデバイスを完全に制御することを難しくする大きな問題だ
必須の銀行アプリの root チェックや Google 関連機能のような重要な部分は文書化されておらず、「スマホの機種 + 地域の銀行アプリ + カスタム ROM」の組み合わせがテスト済みで正常に動く、という情報を見つけるのもほとんど不可能
自由と選択には賛成だが、平均的なスマホ利用者が何台もの端末と何日分もの作業時間を費やすか、そもそも専門家でなければ、現実的な行動様式とは言いにくい
コンピューターではパワーユーザーだが、スマホはもっと愚かでも構わないと思っている
ただしスマホをますます多要素認証デバイスとして使わなければならなかったり、銀行のようにより強いレバレッジを持つ企業の気まぐれに縛られたりすると、そうでいるのは難しくなる
root 化されたスマホで動くアプリを探すために銀行口座を3回も変えるつもりはない
「Android フォークが何の競合だ」と聞くなら、その戦略が効いているということだ
新方式が
/apex/com.android.conscrypt/cacertsがあればそこから証明書を読むのなら、現在の SafetyNet 回避や root 隠し、Magisk 隠しのように、必要なプロセスだけで/apex/com.android.conscrypt/cacertsを隠して、従来方式へフォールバックさせられそうだハッカーだけの領域で、その中でもごく一部だけが使うものだ
ここには良いコメントが多いが、PC がスマホのように動作しないことがどれほどありがたいかを考え続けてしまう
Android は自らをあまりに徹底的に台無しにしていて、Microsoft が Google がスマホ世界を運営するようには PC 世界を運営していないことに感謝している自分が、妙に感じられるほどだ
Windows 自体は Android に比べれば安定性と常識の砦に近く、ハードウェアが実際に老朽化で壊れる前にアップグレードを強制される必要もない
Google と同じく Microsoft もハードウェアからソフトウェアまでのパイプライン全体を支配しているわけではないが、ストアで規範を強制したり、SafetyNet のような仕組みで環境変更を抑え込んだりして、PC の所有を極度に不便にする力はあった
以前 Microsoft がこうしたことで反トラスト訴訟を起こされたことがあったか記憶があいまいだが、Google にも同じことがいつ来るのか気になる
Microsoft も Windows に多数の DRM を追加し、後にそれらを壊しもしたし、リモートアテステーションも OS に組み込まれている
Google は本来依存すべきではない Android の内部実装を変えて開発者を不便にしたわけだが、Microsoft もこういうことは常にやっている
更新された Magisk モジュールを数週間待てばよい可能性が高く、正直そこまで悪くはない
Android 14 を受け取る5〜6台のデバイスで、それまでは更新ボタンを押さなければいいだけだ
Windows 11 は TPM と Secure Boot を要求する
一部の発展途上国がすべての接続に中間者攻撃を仕掛けるために国家 CA のインストールを要求しているという話を聞いたことがあるが、これを非常に難しくすれば、ユーザーに自分のプライバシーを切らせることが現実的に難しくなる
PinePhone Proを日常使いの端末として使っている
Chase.comは、Librewolfのような非標準ブラウザやスマートフォン/タブレットのブラウザ利用を本当に執拗にブロックしようとし、モバイルアプリを使うよう強制しようとする
少なくともWEIが義務化されるまでは、こうした愚かな措置は簡単に回避できるので深刻な問題ではないが、Chaseは銀行なので法的に争う余地があるのか気になる
最初に思いつくのはADA準拠の方面だが、確信はない
もう疲れ果てていて、この件で訴訟を起こしたいという言葉が本気なのかどうかも分からない
枝葉の話ではあるが、モバイルOSの寡占体制から抜け出すのがほぼ不可能だという別の側面を示しているので関係はある
Linuxフォンのニッチ市場が奇跡的に数%まで成長したとしても、Androidは悪化し続ける可能性が高く、何かが必要だ
デジタル農奴制の時代が来る気がする
何らかの「慈悲深い」企業が提供したデバイスを使うことになり、その企業がデバイスのあらゆる側面を所有し、金を払って初めて運転するように使える
ほかの経路はほとんど閉ざされ、汎用コンピューティングは「企業向け」としてだけ残り、「自由なWeb」は存在するだろうが、かなり技術的でユーザーに敵対的なものになるだろう
市場の大半、とりわけ金銭を扱うあらゆる場所は、それを疫病のように避けるだろう
GoogleはこれでオープンWebを殺したと思う
いずれにせよ少し退屈になってきてはいたが、これでスマートフォンや「承認済み」ブラウザなしに生活するのがはるかに難しくなったのは腹立たしい
熟練ユーザーが追加ソフトウェアをインストールして問題を直せるのもよいことだが、Chaseが標準のWebサイトを修正し、同じような必要を持つ初心者ユーザーも助けられるようにするほうが望ましい
この点では、AndroidはAppleよりも強圧的だったし、今もそうだと思う
新しいルートCAをインストールして信頼できたときでさえ、一部のアプリはそれを無視できたし、実際に無視していた
iOSとAndroidはいずれもアプリが証明書ピンニングを使えるが、Android 7+では2016年からデフォルトで、アプリがユーザー追加のCAを無視する[1]
iOSでルートCAを信頼する手順は、プロファイルのインストールと怖い警告を経る形で面倒で、それ自体は妥当だが、経験上ほとんどのアプリは証明書ピンニングを使っていない限りこれを信頼する
[1]: https://android-developers.googleblog.com/2016/07/changes-to...
iOSより一般的なコンピュータにはるかに近いAndroidには、ストーカーウェア問題が非常に大きい
ストーカーウェアはプロンプトでは止められず、後方互換性を武器化し、あらゆる種類の虐待を含む
iOSでは、誰かにスマートフォンを5分貸したあと、何年にもわたってHTTPSのプライバシーが覆されることが驚くほど簡単だ
インストールしたCA証明書を実際に信頼できる選択肢は欲しいが、特にWebブラウザであるFirefoxでさえ、隠れたタブの組み合わせと設定なしにはユーザー証明書を使わないのは腹立たしい
それでも、世界中のAndroidユーザーに生じるリスクを考えると、日常的に使う数十人の技術者にとってこの機能がそれほど重要だとは見なしにくい
今回の件は、地域のIT部門の計画を妨害しようとする邪悪なGoogleの陰謀というより、Googleによる優れたサンドボックス改善と、長く遅れていたCAストア更新メカニズムの副作用に近いと思う
Magiskモジュールがすぐ回避策として出てくるだろうし、既存モジュールはしばらく壊れるだろうが、主要なAndroidアップデート後にはよくあることだ
必要なら自分でモジュールを書くこともできる
これは単にマウントが動作する仕組みなのではないかと思う
/apex/whateverに何かがマウントされていて、各アプリが別々のマウント名前空間を持つなら、自分の名前空間で/apex/whateverの上に再度マウントしても、ほかの名前空間には何の変化もないファイルシステムを直接変更するか、別のアプリのマウント名前空間に入って、そこにもtmpfsをマウントする必要がある
共有マウントが役立つかもしれないが確信はなく、実際に何が起きているのかもっと詳しく見る必要がある
この結果は、root権限でもユーザーがルートCAを変更できないようにする意図的な試みというより、Googleの名前空間/コンテナ化作業の副産物である可能性が高いと思う
ただし最終的な結果は依然として大きな問題だ
ここで驚くべき点は「別々のマウント名前空間」だ
以前はシェルを開いてファイルシステムにマウントしたり直接変更したりすれば、アプリはそのマウントから問題なくファイルを読んでいた
今はこのcacertファイル群についてはそうではなく、新しい方式では直接変更も不可能だ
この変更までは、Androidアプリが独自のマウント名前空間を使っていることすら知らなかった
正確にどう動作するのかの文書はほとんどなく、これまでここまで明確に露呈した事例があったのかもよく分からない
manifest v3を見ればよい
Twitterで著者に返信したが、見ていないかもしれないのでここにも残しておく
Android 14の更新可能な証明書についてのブログ記事を書いた者で、その記事が記事本文にリンクされている
実際には、APEX証明書ディレクトリから読むのを迂回するよう設定できるシステムプロパティがある
system.certs.enabled=true出典: https://android-review.googlesource.com/c/platform/framework...
それは
android.os.SystemPropertiesのOSプロパティ、つまりadbでデバイス全体に設定できる値ではなく、java.lang.Systemプロパティ、言い換えると1つのJVM/アプリ内で設定される構成値私の見立てでは、前者を再設定するにはアプリ自体を修正する必要がある
自動化テスト用だったり、debug/prodビルド間で設定を切り替えたりするには便利だが、デバイス全体でCA証明書を信頼させたい場合にはあまり役に立たない
もちろん、そのようなプロパティを外部から設定して全アプリに適用する方法を知っているなら、本当にうまく機能するはずなのでぜひ聞きたい
ちなみに私が著者で、Twitterではそのような返信は見えていない
いかにも2023年のTwitterらしい
セキュリティには良さそうで、一部の開発者には地獄のようだが、このAndroidバージョンが2〜3年後に見捨てられたらどうなるのかと思う
ハードコードされた証明書があと数年持ちこたえてくれるよう祈るしかないのか
Android 14はルート証明書をGoogle Play経由で更新可能にし、以前のようにルート証明書を追加・削除するためにOTAアップデートを必要としない
今日知った回避策もある [0]
Android 7.0以下を使っている場合、Let’s Encrypt証明書で保護されたWebサイトに引き続きアクセスするには対応が必要になる可能性があり、Android OSの信頼ストアではなく独自の信頼ストアを使うFirefox Mobileのインストールと利用が推奨されているという
[0] https://letsencrypt.org/2023/07/10/cross-sign-expiration.htm...
[1] https://www.xda-developers.com/android-14-root-certificates-...
GoogleのアップデートにはLet’s Encryptが使う中間証明書が入っていなかったため
これは将来の仮定の問題ではなく、今まさに存在している問題
なぜGoogleが、私が誰を信頼するかの最終判定者であるべきなのか
Googleにも明らかに抜け穴はある
そして、すでに承認済みの証明書プロバイダーの中にも、証明書を持つべきでない人や組織に発行した前歴があり、実際には信頼すべきでないところがある
アプリは一般にユーザー証明書を受け入れず、Google Cloudかその関連の何かがより新しい証明書に切り替わったことで、一部のアプリが動作しなくなり始めた
つまりPlay Servicesを通じてアウトオブバンドで更新され、OEMのOSアップデートは不要
Androidのリリースが出るたびに何かが削除され、あまり意味のないものが追加されるのを見ている
iOSは逆方向に進んでいるように見えるので、ゆっくり中間で出会い、後にはiOSがあらゆる面でAndroidを上回るかもしれないように思える
Apple側の人たちに率直な意見を聞きたい
最近macOSを使っているが、Windows/Linuxでは何十年も前から当たり前だったごく基本的なユーザー体験で失敗していて嫌になる
Finderのようなものは本当に最悪
次の世代でAndroidの代わりにiPhoneを買ったら、iOSにも同じような否定的反応をすることになるのだろうか
スマートフォンのユースケースでは、iOSはmacOSよりも完成度が高く有用なユーザー体験だと言えるのか
乗り換えたい気持ちはあるが、時間とお金を無駄にしたくはない
昔のAndroidは単に
.apkがあるiOS以上のものだったのに、本当に残念その用途には問題ない
だがユーザーがあまりに制限されているので、脱獄を調べる手もあるかもしれないが、私はスマホの使用を最小限にして、ほぼすべてのことをデスクトップでやろうとしている
ちなみにmacOSも捨ててLinuxへ移行中の立場
セルフホストしているソフトウェアに接続するために、個人用PKIを使っている
メールサーバー、カレンダープロバイダー、ノートサーバー、写真同期ツールのようなもの
自分のルート証明書を認証局リストに追加できる必要がある
システム提供のリストを変えたいのではなく、単に自分の証明書を追加したいだけ
自分のデバイスなのだから、望むなら何でも変更できるべきだと思う
メールやカレンダーアプリもここに含まれる可能性が高い
うまくいかない可能性が高いのは、独自CAをインストールしてアプリとアプリ開発元サーバー間のトラフィックを傍受する用途
自分のデバイスが何をしているか検査できるべきなので、それは残念だが、セルフホストのソフトウェアに個人用PKIを使うユースケースは明らかにサポートされている
何らかの方法があるはずだと思う
そのためのツールをgetlocalcertで作っている [1]
信頼ルートを追加する必要を避けられるので、一部のネットワークでは「プライベートネットワーク上の公的証明書」というアプローチが全体として得になる
正直、AndroidがプライベートCAをブロックするとは予想していなかったが、結局こうなった
[1] https://www.getlocalcert.net/
今はAndroidスマホを使っていないが、以前はroot権限なしで設定内のオプションだけで独自CA証明書をAndroidスマホに追加でき、少なくともWebブラウザのようなアプリはそれを信頼していたと記憶している
それほど大昔の話でもない
なので、カスタム証明書のインストールにデバイスのroot化が必要な理由が、何か別の用途なのか理解できなかった
HTTP Toolkitは、トルコのひどいEV充電アプリから隠れたAPIを抽出するのにとても役立った
SSLピンニングとroot検出を回避するためにFridaも併用した
そのうち、彼らがAPIを隠そうとしている理由は、そのAPI群が怪物じみた代物だからなのかもしれないと気づいた /s