🔥

LinuxシステムでのTPMを使ったフルディスク暗号化における(現状の)問題点

に公開

あらすじ

WindowsやmacOS、ChromeOSやAndroidなど一般的なOSの世界ではディスクやユーザーデータを暗号化するのはもはや当たり前になりつつあります。Linuxシステムにおいても、TPM(Trusted Platform Module)を使用したディスク暗号化の仕組みが整備されつつあり、実際にopenSUSE Aeonなど一部のディストリビューションはこれを採用しています。

この記事では、clevisやsystemd-cryptenrollが行う現状のLinuxシステムにおけるフルディスク暗号化の問題点について、思ってることを書いていこうと思います。

https://wiki.archlinux.jp/index.php/Systemd-cryptenroll
https://wiki.archlinux.jp/index.php/Clevis

現状

clevisやsystemd-cryptenrollは、TPMのPCRというシステムを使用してOSの整合性を確認した上で、自動的にディスクの暗号化を解除する方法を採用しています。PCRにはTPMによって測定されたOSの各コンポーネントの状態を示すハッシュが格納され、これを確認することでOSの整合性をチェックすることが可能になります。
TPMのPCRには複数の階層があり、各層はブートローダーやカーネル、セキュアブートの設定などそれぞれのコンポーネントに対応しています。この対応表は全てのディストリビューションで共通のものが定められています。
https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/

ディスクの暗号化を自動的に解除する場合、システムの整合性が確保されていることは必須です。例えハードウェアから鍵を抜け出せなかったとしても、カーネルパラメーターにinit=/bin/shなどを設定することで、簡単にOSの認証を突破できてしまうからです。例えばGRUBを使用している場合、このカーネルパラメーターのハッシュはPCR8に保存されます。

systemd-cryptenrollなどのハードウェアベースのディスク暗号化のソリューションは、通常複数のPCRを読み取り、システムの整合性を確認した上でTPMの鍵を用いてディスクを復号化するように設定します。

tpm2_pcrreadコマンドを実行すると、現在実行してるシステムのTPMのPCRのハッシュを確認することができます。
PCRの値を示す、tpm2_pcrreadコマンドの実行結果1

PCRの値を示す、tpm2_pcrreadコマンドの実行結果2

問題点

ここまでは何の問題もなさそうに見えますが、外の世界に目を向けるとこのシステムはやや不十分であるように見えてきます。

フルディスク暗号化のみでデータを保護するのは、もはや時代遅れ

macOSのFileVaultやiOS, Android, ChromeOSなど最近のOSのユーザーデータの暗号化機能は、ディスク全体を単一の鍵で暗号化している訳ではありません。
ファイルベースでユーザーディレクトリのデータを、ハードウェアの鍵とユーザーのログインパスワードの組み合わせで導出される鍵を用いて暗号化します。
https://source.android.com/docs/security/features/encryption/file-based?hl=ja

ファイルベースの暗号化を行うAndroidの場合、システムの整合性はフルディスク暗号化ではなく、他の仕組みを使って確保しています。
https://source.android.com/docs/security/features/verifiedboot/avb?hl=ja
https://source.android.com/docs/security/features/verifiedboot/dm-verity?hl=ja

これはディスク全体を単一の鍵で暗号化するよりも安全であり、理にかなっています。
ディスク全体を単一のハードウェアベースの鍵で暗号化する場合、仮にOSの整合性が確認されていたとしても、ログイン画面をバイパスする脆弱性を使用する攻撃や、USB・Thunderbolt・PICeなどのバス経由でカーネルに対して行われる攻撃に対しては脆弱なままです。ログイン前にネットワークに接続するシステムの場合は、sambaなどを悪用したローカルネットワーク経由での攻撃にも脆弱になります。
攻撃者がデバイスを盗んだ場合、そのデバイスのOSを改ざんせずとも、例えばUSB経由でマウントされたドライブにアクセスできる脆弱性がカーネルに存在した場合、その時点でディスク暗号化はもはや何の意味も持ちません。ドライブのみが盗難された場合には依然として有効ですが、最近の分解しにくいラップトップなどを考えるとデバイス全体が盗難される確率の方が高いことは明らかです。

ユーザーのログインパスワードとハードウェアベースの鍵から導出される鍵を用いてユーザーディレクトリの内容を暗号化すれば、この種の攻撃からシステムを守ることができます。

OSのディレクトリには、整合性のみが確保されていれば良いものと、整合性と機密性の両方が確保されていなければならないディレクトリがあります。Linuxシステムにおいては、OSのシステムファイルなどを格納した/usrなどのディレクトリが前者に該当し、/home/etc、場合によっては/varなどが後者に該当します。

フルディスク暗号化はこれらを区別せず全てを単一の鍵で暗号化し起動中に復号化しますが、本来機密性が求められるディレクトリのみを、ユーザーのログインパスワードなどで暗号化し、ログイン時にシームレスに復号化すれシステムを採用すれば機密性自体は十分に守れるはずです。
幸いなことに、fscryptなどを使用してこの作業を自動で行ってくれるsystemd-homedというツールが既に存在します。
https://wiki.archlinux.jp/index.php/Systemd-homed

整合性のみを守る必要があるディレクトリに対しては暗号化自体は不要で、ChromeOSやAndroidが行ってるようなdm-verityとセキュアブートの組み合わせなど他の方法での保護を検討するべきだと考えています。

TPMのPCRはあまり宛にならない

第二の問題として、そもそもTPMのPCR自体がLinuxシステムにおいてはあまり宛にならないことが挙げられます。例えばclevissystemd-cryptenrollを使用して暗号化されたほとんどのシステムはPCR7(と設定によって定義された他のPCR)を読み取ってセキュアブートが有効であることを検証しますが、このPCR7のハッシュ値はセキュアブートのDBX(失効リスト)のアップデートなどでも変動します。PCR0~2もUEFIのアップデートで変動するなど、かなり一般的な操作でTPMのPCRのハッシュ値が予想されるものから変わってしまいます。
かと言ってこれらのPCRをチェックしない場合、物理的なアクセスを持つ攻撃者やUEFIなどデバイスのファームウェアに感染する悪意のあるソフトウェアからの攻撃に対して脆弱になってしまいます。
現状では、多くの場合システムの管理者はセキュリティを維持しつつ高頻度でリカバリーキーを入力する手間を選ぶか、ある程度セキュリティを犠牲にして使いやすさを選択するかの2択を迫られているのが実情です。

そもそもWindowsプラットフォームのセキュアブート自体あまり強力ではない

第二の問題が出てくるそもそもの問題として、Windowsプラットフォームのセキュアブート自体があまり強力ではないことが挙げられます。というのもMicrosoftは各ディストリビューションのshimなど多くのバイナリに署名しているため、Chain of Trustをセキュアブートのみで構築すること自体が困難です。というのも、仮にカーネルが特定の鍵で署名されたパーティションやinitrdしかロードしないように構築されていたとしても、Microsoftの鍵で署名された別のディストリビューションのカーネル(をロードするshim)を使用すれば簡単に信頼の連鎖を破壊できてしまうからです。

他のOSでのソリューション

ChromeOS Flex

ChromeOS FlexはTPM(利用可能な場合)とユーザーのログインパスワードを用いてユーザーデータを暗号化し、UEFIセキュアブートを使ってカーネルの整合性を検証しています。
UEFIセキュアブート自体はそこまで強力ではないものの、TPMを使うことでログイン(ユーザーデータの復号化)の試行にハードウェアベースのレートリミットを実装することに成功しています。
https://www.chromium.org/chromium-os/chromiumos-design-docs/protecting-cached-user-data/#managing-encryption-keys

残念なことに、ChromeOS FlexでTPMを使用できるモデルは非常に限られています。それ以外のモデルではソフトウェアベースの保護にフォールバックしますが、それでもユーザーデータはログインパスワードで暗号化されています。

macOS

macOSはdm-verityに相当するSealed System Volume(署名済みシステムボリューム)とTPMに相当するSecure Enclave、そしてユーザーのログインパスワードの組み合わせで効果的にこの問題に対処しています。

機密性が必要ないシステムデータはSSVで保護され、ユーザーデータはSecure Enclaveの鍵とログインパスワードの組み合わせで導出される鍵を使って暗号化されています。
https://support.apple.com/ja-jp/guide/security/secd698747c9/web
https://support.apple.com/ja-jp/guide/security/sec4c6dc1b6e/web

まとめ/ソリューション

  • ここで挙げた多くの攻撃は、Linuxシステムにおいてもsystemd-homedなどのホームディレクトリを暗号化するプログラムを使うこと、TPMでの復号化にPINを要求するように設定するなどのHardeningで緩和することができます。もちろんこれらにも欠点はありますが、それはまた別の問題だと考えています。
  • 欠点があるからと言って現状のTPMベースのディスク暗号化に効果がないと言っている訳ではありません。完璧なセキュリティのソリューションは存在しません。一部の攻撃に対しては依然として効果があり、セキュアブートやディスクの暗号化が無効になっている状態よりは遥かに優れてると言えます。
    • この手の話題をすると「そもそもデバイスの盗難なんて事態を考える意味はない」だとか「そんなシステムなくても昔は上手く行っていた」、「TPMやセキュアブートは所有者の権利を制限する悪の手先だ」みたいなディスクの暗号化や、ハードウェアベースのセキュリティ機構そのものを否定するコメントが飛んでくるのを見かけますが、個人的にはそのような意見には全く同意できません。
    • 特にスマートフォンやラップトップなど、持ち歩くデバイスでは物理的な攻撃に対するある程度の耐性は必須だと考えています。
  • Linuxシステムのハードウェアベースのディスク暗号化機能や、セキュアブートの実装はまだまだ発展途上です。systemdやUbuntuなどの最近の動向などからも、今後それぞれの実装がより改善されていくものだと私は考えています。

Discussion