TPM 通信から BitLocker の鍵を窃取し、暗号化されたボリュームを復号する手順をエミュレーターでお手軽に体験する方法を紹介します。 TPM と BitLocker が対策可能な脅威とはなんなのか、理解を深めるきっかけになればと思います。
準備
前回の記事で QEMU エミュレーターに Windows 11 をインストールし、TPM 通信をキャプチャするまでの手順を紹介しています。 本稿では引き続きこの環境を使用します。 時間はかかりますが PC が 1 台あればコピペでできるので、時間のある方はぜひチャレンジを💪。
時間の無い方向けに 3 行で説明すると
- Linux 上に Windows 仮想マシン(QEMU)を作成
- 仮想マシンの TPM に TPM エミュレーター(SWTPM)を使用
- 仮想マシンと TPM エミュレーター間の通信を弊社製ライブラリでキャプチャ
BitLocker 有効化
QEMU Windows を起動して BitLocker を有効化します。 この手順では TPM 通信をキャプチャしておく必用はありませんが、キャプチャしておくと後で解析を楽しめるかもしれません。 コマンドを再掲します。
SWTPM(TPM シミュレーター)を起動:
while true; do swtpm socket --tpmstate dir="$HOME"/swtpm --tpm2 --server port=2321 --ctrl type=tcp,port=2322; done
TPM 通信プロキシを起動:
go run github.com/CyberDefenseInstitute/tpmproxy/example/qemu_swtpm_forward@latest
QEMU Windows(仮想マシン)を起動:
qemu-system-x86_64 \
-machine q35,accel=kvm \
-m 4096 \
-cpu host \
-smp 2,sockets=1,dies=1,cores=2,threads=1 \
-display spice-app \
-nic none \
-drive file="$HOME"/win11.qcow2,if=virtio,format=qcow2,discard=unmap \
-drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE_4M.secboot.fd,readonly=on \
-drive if=pflash,format=raw,file="$HOME"/OVMF_VARS_4M.ms.fd \
-chardev socket,id=chrtpm,path=/tmp/qemu_swtpm_fwd.sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0
コントロールパネルから BitLocker 管理画面を開き、BitLocker を有効化してください。 本稿では BitLocker 回復キーを C ドライブ直下に PDF 出力しておき、暗号化ボリュームからこの PDF ファイルを取り出せたら復号成功、と目標を設定しておきましょう😄
完了したら Windows をシャットダウンしてください。 スナップショットも取っておくといいかもしれません。
qemu-img snapshot -c bitlocker "$HOME"/win11.qcow2
TPM 通信から BitLocker の鍵を窃取
qemu_swtpm_dissect を使って TPM 通信から BitLocker の鍵を窃取します。 現実には PC を開封して TPM を発見し、プローブ用の導線をはんだ付けしてロジックアナライザで通信を解析するような作業をイメージ頂ければと思います。
go run github.com/CyberDefenseInstitute/tpmproxy/example/qemu_swtpm_dissect@latest
先程同様に QEMU Windows を起動すると・・。
qemu-system-x86_64 \
-machine q35,accel=kvm \
-m 4096 \
-cpu host \
-smp 2,sockets=1,dies=1,cores=2,threads=1 \
-display spice-app \
-nic none \
-drive file="$HOME"/win11.qcow2,if=virtio,format=qcow2,discard=unmap \
-drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE_4M.secboot.fd,readonly=on \
-drive if=pflash,format=raw,file="$HOME"/OVMF_VARS_4M.ms.fd \
-chardev socket,id=chrtpm,path=/tmp/qemu_swtpm_fwd.sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0
qemu_swtpm_dissect には UnsealResponse
から始まる次のような文字が表示されるかと思います。
UnsealResponse: 2c000000010000000320000031828e27937d83409541a3049170abc4e94be4926b8462e6215223acb4cee7b3
31828e27937d83409541a3049170abc4e94be4926b8462e6215223acb4cee7b3
の部分が BitLocker の鍵を復号するための鍵である VMK(ボリューム マスタ キー)です。
読者のみなさまの環境では異なる値が表示されていると思います。
Wireshark に慣れている方は、ぜひ Wireshark でも VMK の取得にチャレンジしてみてください🦈
取得した VMK をファイルに保存しておきます。
echo -n <UnsealResponse の値> | tail -c 64 | xxd -r -p > "$HOME"/vmk.bin
エミュレーターの仮想ストレージを Linux でマウントする
QEMU Windows はシャットダウンしてください。 エミュレーターの仮想ストレージファイルを Linux でマウントします。 現実には Windows PC から暗号化されたストレージを取り外して、Linux PC に接続するような作業をイメージ頂ければと思います。
sudo modprobe nbd
sudo qemu-nbd -c /dev/nbd0 "$HOME"/win11.qcow2
ls /dev/nbd0p*
/dev/nbd0p1 ~ /dev/nbd0p4 が表示されたかと思います。 パーティション毎に分かれていて /dev/nbd0p3 がお目当ての BitLocker 暗号化ボリュームです。 ボリュームの情報を少しのぞいてみます。
sudo apt install libbde-utils
sudo bdeinfo /dev/nbd0p3
BitLocker 回復キーの方は先程 PDF で見たのと同じ ID ですね。
$ sudo bdeinfo /dev/nbd0p3
bdeinfo 20190102
BitLocker Drive Encryption information:
Encryption method : AES-XTS 128-bit
Volume identifier : 0acac894-27bf-4446-9fc7-cbd5f22ca5f9
Creation time : Oct 10, 2024 05:10:54.840129500 UTC
Description : DESKTOP-IPILQ44 C: 10/10/2024
Number of key protectors : 2
Key protector 0:
Identifier : 82703178-414d-4c96-b489-1a3405f6ba01
Type : TPM
Key protector 1:
Identifier : ee9ed5b9-8aa2-4358-b3e7-25242731a6ac
Type : Recovery password
暗号化されたボリュームを復号する
いよいよですね・・! 取得した VMK(ボリューム マスタ キー) と Dislocker を使って暗号化されたボリュームを復号します。 ここまで来るとエミュレーターでも現実でも同じ作業です。
sudo apt install dislocker
mkdir -p "$HOME"/mnt/{dislocker,win11_c}
sudo dislocker -vvvv --readonly --volume /dev/nbd0p3 --vmk "$HOME/vmk.bin" "$HOME"/mnt/dislocker -- -f
sudo mount --read-only --options loop --options uid="$(id --user)",gid="$(id --group)" "$HOME"/mnt/dislocker/dislocker-file "$HOME"/mnt/win11_c
ファイラーで "$HOME"/mnt/win11_c 以下の PDF を探して・・。
開けたー🙌
お片付け
PDF やファイラーを終了後、マウント解除します。 現実には Linux PC から暗号化されたストレージを取り外して、Windows PC に戻す作業をイメージ頂ければと思います。
sudo umount "$HOME"/mnt/win11_c
sudo umount "$HOME"/mnt/dislocker
sudo killall qemu-nbd
なにが起きたのか
簡単に噛み砕いた技術解説を試みたいと思います。
まず BitLocker の通常の動作をざっくりと:
- BitLocker 有効化時、ボリュームを暗号化する鍵が生成されます: FVEK(フル ボリューム暗号化キー)
- FVEK を暗号化する鍵が生成されます: VMK(ボリューム マスタ キー)
- TPM オブジェクトを生成し、VMK を封印します(TPM を使って VMK を暗号化するような感じです)
- Windows のブート時、TPM オブジェクトに封印した VMK を開封します(TPM を使って VMK を復号するような感じです)
- VMK を使って FVEK を復号します
- FVEK を使ってボリュームを復号します
VMK 開封の儀は TPM を使ったブートプロセスの検証によって行われます。 例えば VMK を窃取するためのブートマネージャーをインストールして起動したりすると、VMK は開封できません。 しかし TPM 通信をキャプチャできれば、ブートプロセスを改ざんせずに VMK を窃取可能です。 TPM 通信自体は通常は暗号化されないことが多く、VMK 開封に使われる TPM2_Unseal コマンドも開封したデータはクリアテキストで返すことになっています。
そのため TPM 通信キャプチャ => VMK 窃取 => FVEK 復号 => ボリューム復号
が成功します。
まとめ
TPM 通信がキャプチャされるとどうなるのか、TPM 利用例の代表格と言える BitLocker に登場してもらいつつ、TPM 通信から BitLocker の鍵を窃取し、暗号化されたボリュームを復号する手順をエミュレーターでお手軽に体験する方法を紹介しました。 どのような条件下で BitLocker 暗号化ボリュームが復号可能になるのか想像しやすくなった、と思って頂けたら幸いです。
そして、賛否両論かもしれませんが、これはあくまでも BitLocker の仕様であり脆弱性ではないことを理解するのが重要だと思います。
もちろん TPM の脆弱性でもありません。
"TPM のみ"の場合 多くのスキルを持たない、または物理的なアクセスが制限されている攻撃者
の攻撃の緩和策にはなりえますが、スキルと長い物理的アクセス権を持つ攻撃者
の攻撃への緩和策とはならないことが Microsoft 社のドキュメント BitLocker の対策: 攻撃者の対策 に書かれています。
既にご存知の方にはここまでモヤモヤさせてしまったかもしれませんが、グループポリシーにより BitLocker の認証方法を強固なものに変更出来ます。
スキルと長い物理的アクセス権を持つ攻撃者
の攻撃への緩和策としては TPM+PIN 認証の使用かつスリープモードの禁止があげられています。
BitLocker 誕生から長い年月が過ぎた今、本稿のような攻撃を実際の PC と TPM に対して実現可能な攻撃者は増えたと見るべきでしょう。 守るべき資産に対して十分なセキュリティ対策ができていないかもしれない、と感じた方は検討が必用かもしれません。
次回予告
サイバーディフェンス研究所では TPM リモートアテステーション技術を信頼の起点としたゼロトラストシステム PIV Gateway™ の研究開発を行っています。 PIV Gateway™ は TPM 通信パラメーターの暗号化に対応しています。 次回は TPM 通信パラメーターの暗号化とは何か、なぜ BitLocker で利用されていないのか、実用化に至るまでの厳しい課題など紹介できればと思います。 書くのにとても時間がかかりそうなので、TPMProxy は SWTPM だけでなく本物の TPM の通信もプロキシできるという小ネタを挟むかもしれません。
それでは、よい TPM ライフを👋