最近「Confidential Computing」の勉強を始めました。
IBM の Confidential Computing のサイト (https://www.ibm.com/cloud/confidential-computing) には「Protect your data at rest, in transit and in use. Get a higher level of privacy assurance.」というキャッチフレーズが書かれています。
データを保存中、移動中、使用中であってもより高いレベルで保護すると言っています。
保存中の保護はストレージの暗号化ですね。
移動中の保護は通信の暗号化、ssh や https などが思いつきます。
使用中とは、メモリー上のデータの保護です。
そして Confidential Computing では「やらない」ではなく「出来ない」確証を求めます。
「アクセスしません」「ルールで許可していません」ではなく「アクセスや改変をしようと思っても機能として出来ない」ことの確証です。
IBM Cloud 上の Confidential Computing 機能
IBM Cloud では IBM® Z®およびLinuxONEシステムの機能を活用したConfidential Computing 機能を提供しています。主要なものを紹介します。
- IBM Cloud Hyper Protect Crypto Services
FIPS 140-2レベル4認定ハードウェアで構築された業界唯一の鍵管理およびクラウド・ハードウェア・セキュリティー・モジュール(HSM)のサービスです。強力な暗号化機能を提供します。
- IBM Hyper Protect Virtual Servers
IBM® Z®およびLinuxONEシステム上 に構築された Hypervisor からは暗号化された Linux 実行環境です。
Secure Build Server の機能を利用し、署名・暗号化したイメージから root ログインができないアプリケーション実行環境も提供します。
- IBM Cloud Hyper Protect DBaaS
組み込みの暗号化を提供するマネージド型データベースです。
MongoDB、PostgreSQL が用意されています。
検証内容
今回は Hyper Protect Virtual Servers ではない通常の環境の危険性を確認します。
検証アプリケーションと環境
IBM が GitHubに公開している Secure Bitcoin Wallet というコンテナアプリケーションのビットコイン・ウォレットを利用します。
Hyper Protect Virtual Servers 上の構築を想定したもののようですが x64 環境でも稼働するので、Windows 10 Pro の Hyper-V に導入した Ubuntu Server 20.04 LTS 上で稼働させます。
これは OS にログインできなくても Hypervisor にアクセスできればデータの取得ができることを確認するためです。
ターゲットはビットコイン・ウォレットのseed
「シードフレーズとは」に、こう記載されています。
シードフレーズとは、仮想通貨ウォレットへのアクセス回復に使用できる単語のリストのことです。ニーモニックフレーズやパスフレーズとも呼ばれます。特定の仮想通貨固有のものではないため、1つのシードフレーズによってポートフォリオ全体へのアクセスを回復することができます。
シードフレーズは、ウォレットの秘密鍵から暗号で派生した単語のシーケンスで、BIP39ワードリストと呼ばれる2,048の英単語から取られた、12〜24語の単語をランダムに並べたものです。
多くの仮想通貨ウォレットソフトウェアは、シードフレーズを生成し、ユーザーに対してそれを紙などに書き留めるよう指示します。これにより、ハードウェアが故障や紛失、盗難などにあった場合でも、ウォレットソフトウェアを再度ダウンロードすることで、シードフレーズを用いて資産へのアクセスを回復できます。
シードフレーズを知っている人であれば誰でもチェーン上の資産へアクセスできるため、シードフレーズを記した紙は安全に保管する必要があります。もし、何者かによって自分の資産を送金されてしまった場合、ブロックチェーンの性質上、元に戻すことはできません。
つまり、ビットコイン・ウォレットの seed を盗み見ることができれば、ビットコイン・ウォレットを乗っ取ることができるわけです
検証
では、Confidential Computing ではない環境で ビットコイン・ウォレットの seed を盗み見ることが技術的にできるか検証してみましょう。
準備
Windows 10 Pro の Hyper-V に Ubuntu Server 20.04 LTS を VM として導入しておきます。
GUIは不要です。
GitHub にアカウントを作成し、アクセストークンを作成しておきます。
アプリケーションの導入
Ubuntu にログインします。ログインユーザーが root でない場合、root に移行します。
sudo -s
GitHub のアクセストークンを環境変数に設定します。
export ACCESS_TOKEN=[ご自身のアクセストークン]
解析に使うツールをインストールします。
その後、GitHub からサンプルアプリケーションを clone し build します。
apt-get update
apt-get install -y gdb binutils
apt-get install -y git docker.io
git clone https://github.com/IBM/secure-bitcoin-wallet.git
cd secure-bitcoin-wallet
docker build --build-arg NO_GRPC_BUILD=1 --build-arg ACCESS_TOKEN=${ACCESS_TOKEN} -t secure-bitcoin-wallet .
docker image ls
コンテナイメージが作成されました。
アプリケーションの起動
アプリケーションを起動します。
ビットコイン・ウォレットのコンテナを 3 つ起動するスクリプトが用意されているので、そちらで起動します。
cd scripts/
./reset_all.sh
3 つのビットコイン・ウォレットがコンテナとして起動しました。
ターゲット・コンテナの PID の確認
今回、攻撃対象にするのは 4431 ポートで稼働している charlie-wallet です。
「docker ps」でコンテナ ID が「2fc7e988e1e3」であることが分かります。
root@u2004:/home/user01/secure-bitcoin-wallet/scripts# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef2e8df189bc secure-bitcoin-wallet "/usr/bin/supervisord" 40 minutes ago Up 40 minutes 0.0.0.0:4433->443/tcp, :::4433->443/tcp eddy-wallet
029f2cc5861b secure-bitcoin-wallet "/usr/bin/supervisord" 40 minutes ago Up 40 minutes 0.0.0.0:4432->443/tcp, :::4432->443/tcp devil-wallet
2fc7e988e1e3 secure-bitcoin-wallet "/usr/bin/supervisord" 40 minutes ago Up 40 minutes 0.0.0.0:4431->443/tcp, :::4431->443/tcp charlie-wallet
「docker top 2fc7e988e1e3 | grep run_electrum」で攻撃対象の PID を確認します。
今回は「19959」です。
root@u2004:/home/user01/secure-bitcoin-wallet/scripts# docker top 2fc7e988e1e3 | grep run_electrum
root 19959 19737 7 06:02 ? 00:03:21 python3 ./run_electrum daemon --testnet
攻撃対象のウォレットの作成
先ほどの実行結果にウォレットにアクセスする url が記載されていました。
wallet container: charlie-wallet url: https://175.134.119.7:4431/register
wallet container: devil-wallet url: https://175.134.119.7:4432/register
wallet container: eddy-wallet url: https://175.134.119.7:4433/register
ただ「ip a」で確認すると、ホストの IPは「172.26.162.155」でした。
Hyper-V のホストになっている Windows から、攻撃対象のウォレット・コンテナに下記の url で アクセスします。
https://172.26.162.155:4431/register
証明書が確認できないため警告が出ます。「詳細設定」をクリックします。
「172.26.162.155 にアクセスする(安全ではありません)」をクリックします。
charlie というユーザーを登録します。
ウォレットを作成します。ここで入力するパスワードはウォレットを暗号化するもので先ほどのログイン・パスワードとは別のものです。
「Create wallet」をクリックすると、ウォレットが作成されます。seed を指定しない場合、自動生成されます。
今回は「amused clump viable lizard wonder scene humble electric cash scorpion below couch」となりました。
root ユーザーによるハッキング
seed はシステムにより生成されました。コンテナ内のメモリーに残っている可能性があります。
先ほど調べておいたプロセスをダンプします。
gcore 19959
コアファイルから「"seed"」という文字列を検索します。
strings core.19959 | grep \"seed\"
seed が確認できました。
これで、Linix の 管理者である root ユーザーからハッキングされる可能性があることが判明しました。
Hypervisor 管理者によるハッキング
Hypervisor 管理者はログインしなくてもメモリーダンプを取得することができます。
今回は Hyper-V のスナップショットを利用してメモリー内の情報にアクセスします。
Winodws には 標準で strings コマンドがないので Sysinternals のものを使います。
メモリーの状態はスナップショットの「.VMRS」ファイルに含まれます。
PowerShell で「.VMRS」ファイルから「"seed"」という文字列を検索し、その継続 4 行と一緒に出力します。
この処理には時間がかかります、気長に待ちましょう。
C:\tools\strings64 -a C:\vm\Ubuntu2004\Snapshots\37B4229B-7156-4FF0-A767-50F8AA5AC2DD.VMRS | Select-String -Pattern '"seed"' -Context 0,4
seed が表示されました。この方法でも seed をハックすることができました。
Hypervisor 管理者からもハッキング可能なことが判明しました。
Hypervisor 管理者であれば、VM の root 権限も不要です。
charlie としてウォレットを使う
作成したウォレットの画面で「Load wallet」をクリックします。
リロードの指示が出るので、ブラウザーをリロードします。
ビットコインの受け取りアドレスが表示され利用の準備ができました。
「Receiving address」の「mhY3UQmtiphFxiC9DY28RmkxLk4NPuew2D」にビットコインを送金してもらえば、受け取ることができます。
ビットコインを受け取る
ハッキングされビットコインを盗まれるためには、ビットコインを持っている必要があります。
つまり、どこかからビットコインを入手する必要があります
今回のウォレットは開発・テスト環境である「Testnet」と呼ばれるネットワークに接続しています。
Testnet(テストネット)とは
ビットコインには開発のためのテストを行うネットワークとしてTestnet(テストネット)が用意されています。
開発中のコードで本物のビットコインを使ってしまうと、何らかのエラーが起こってしまったときにビットコインを失ってしまうリスクがあります。
そうしたリスクを避けるために、正規のビットコインネットワーク(=Mainnet)とは別にTestnetネットワークが存在しており、そこでは価値を持たない擬似的なコインを本物のビットコインのように取り扱うことができます。
Testnet上のビットコインを受け取るには?
Testnet上のビットコインはTestnet用のFaucetから入手できます。
「Faucet」とは「蛇口」を意味し、蛇口をひねると水が出てくるように、Testnet上のビットコインを入手できるためそう呼ばれています。誰かが無償でTestnet上のビットコインを送ってくれることで成り立っているのです。
そのため、必要以上に利用しない、使い終わったら指定されたアドレスに送り返すなどといったマナーをしっかり守ることが大切です。
「Bitcoin Testnet Faucet」で検索するとテスト用にビットコインを送金できるサイトが見つかります。
今回は、下記を利用してみましょう。
https://bitcoinfaucet.uo1.net/
「Receiving address」の「mhY3UQmtiphFxiC9DY28RmkxLk4NPuew2D」に「0.0001」ビットコイン送金します。
charlie のウォレットを確認すると Balance は増えていません。送金した0.0001ビットコインのトランザクションの Date は表示されず Unconfirmed になっています。
これはビットコインの送金・着金がその当事者間だけで行われるだけではなく、ブロックチェーン台帳に登録される必要があるために遅れです。
しばらくすると登録が終わり Date に日時が入り、Balance が増え、Unconfirmed が消えます。
これで charlie のウォレットにビットコインが入金されました。
ビットコイン・ウォレットを乗っ取る
二つ目のウォレットを使ってビットコイン・ウォレットを乗っ取りましょう。
利用する url は下記です。
https://172.26.162.155:4432/register
証明書が確認できない警告を受け入れ、devil としてユーザー登録します。
ハッキングした seed でウォレットを作ります。
ウォレット を LOAD しブラウザーをリロードします。
最初から「0.0001 BTC」持っていることが分かります。ビットコイン・ウォレットの乗っ取りに成功しました。
乗っ取ったビットコイン・ウォレットから送金する
3つ目のウォレットに乗っ取ったウォレットから送金ビットコインを送金します。
3つ目のウォレットの url は下記です。
https://172.26.162.155:4433/register
証明書の警告を受け入れ、ユーザー eddy を登録します。
ウォレットを通常通りに作ります。seed は自動生成させます。
Load wallet しブラウザーをリロードし、Receiving address を確認します。
devil は乗っ取ったウォレットの「send」タブから上記で表示された Receiving address に送金します。
「MAX」をクリックします。持っている「0.0001 BTC」より小さな金額しか入りませんが、これは、トランザクションの手数料が引かれているためです。
「Send」をクリックし処理が正常に行われるとトランザクションの ID が表示されます。
charlie のウォレットを見てみましょう。ビットコインは残っていません。
安全ではない環境でウォレットを使ったため、すべて盗まれてしまいました。
補足
今回の検証では、構築を容易にするために、同一の Linux 上で 3 つのコンテナを稼働させましたが、各々のウォレットは独立していて、やりとりはすべて Testnet を介して行われています。Linux 内部でのやりとりは行われていません。
別のホストでコンテナを稼働させても構いませんし、2つめ・3つめのウォレットは Testnet につながっていれば、任意のビットコイン・ウォレットで構いません。
まとめ
安全な環境でない場合、root ユーザーや Hypervisor 管理者に悪意があれば、メモリー上のデータが盗まれてしまうことが確認できました。
z15 の Secure Execution では Hypervisor から VM にアクセスできないようになっています。メモリを Swap out する時に Ultravisor (firmware) が暗号化してから Hypervisor に渡すため、Hypervisor 管理者 であってもメモリーの内容を確認することはできません。
IBM Hyper Protect Virtual Servers には「Secure Build Server」という機能ああります。
こちらで構築すれば、root ユーザーを含め誰も OS レベルのログインはできなくなります。
これで、悪意のある root ユーザーからもデータを守ることができます。
IBM Hyper Protect Virtual Servers 上での Secure Build Server の構築・利用の手順は IBM Cloud Docs にチュートリアルとして紹介されています。
次回は、このチュートリアルに挑戦したいと思います。
実施結果は、こちらです。