今週、Bybitが史上最大となる2000億円規模のハッキングを受けたことが話題になりました。これを受けてBybitでは大規模な引き出しラッシュが起こったことからも、この事件をきっかけに取引所に預けている姿勢を見直したユーザーもかなり多かったのではないでしょうか。

喉元すぎれば暑さ忘れる、というようにほとぼりが冷めたら再入金するユーザーもけっこういるのかもしれませんが。

今回の事件で特徴的だったことの1つは攻撃手法が割とすぐに明らかになったことでした。昨年5月末のDMM Bitcoinの事件について攻撃手法の詳細が未だに公表されていないのと対照的に、Bybitの事件は発生直後から原因がわかっており、それが早期の出金再開につながったとされています。

もし原因不明であれば別の資産への影響を調査するために出金を停止する必要が出てきます。とはいえ、いずれにしても出金は停止するほうが様々な賢明だったような気はしますが、結果的にはBybitはこの対応によってユーザーの信用を得られたようです

どちらの事件も資金洗浄の特徴から北朝鮮の政府系ハッカー集団TraderTraitorによるものと考えられていますが、それ以外にも「秘密鍵自体を狙うのではなく、不正なトランザクションに署名させる」という特徴があります。私達のようなセルフカストディしている一般ユーザーもこの種の攻撃に脆弱なのでしょうか?ビットコインユーザーの視点で、Bybitの事件から得られる学びを考えてみましょう。

・ハッカーはどこを狙い、署名者はなぜ気づかなかったのか

・いちビットコインユーザーとして取れる対策はあるのか

ハッカーはどこを狙い、署名者はなぜ気づかなかったのか

今回の事件で流出したのはBybitのコールドウォレットに保管されていたETHでした。DMMに引き続き、コールドウォレットからの流出だったので金額が非常に大きいのが特徴です。

そもそもイーサリアムにはネイティブでマルチシグというものが存在しないため、このコールドウォレットもスマートコントラクトで実装されているものでした。BybitはこれにLedger Nano S(ハードウェアウォレット=HWW)を使って署名を複数追加した送金指示を送るという方法で操作していましたが、実はその指示内容(宛先アドレスや金額)が誤っており、さらにそれに気づかずに署名してしまったことが仇となってしまいました。

スマートコントラクト呼び出しの内容がどのように書き換えられてしまったかというと、Bybitはコールドウォレットを使用する際にSafe(旧Gnosis Safe)という皮肉な名前のWebインターフェイスを使っていました。このWebインターフェイスがクラウドから読み込むJavascriptライブラリが不正なものに書き換えられていたのです。このJavascriptが署名前にトランザクションを書き換えてしまう(攻撃者の用意した別のスマートコントラクトへと送金する)ものになっていました。

手法としては従業員の持つクラウドAPIキーが奪取され、知らないうちに不正なJavascriptライブラリに置き換えられていたようです。フロントエンド自体が改ざんされていたわけではなかったようなので、単純なSRIチェックなどあればJavascriptファイルの改ざんは検知できたように思えます。今回は発生していないフロントエンドの改ざんに備えて取れる手段も多数あったでしょう。

なお、Gnosis Safeは多数のユーザーを抱えるプラットフォームですが、今回の攻撃は巧妙に設計されていて、トランザクションを書き換える処理は特定のターゲットによる署名前にのみ発生するようになっており、それ以外のユーザーに対しては発覚を防ぐために特に改ざんは行わないという完全な標的型攻撃でした。

それではなぜ署名者は署名対象データがすり替えられていることに気づかなかったのでしょうか?それはBybitが使用していたLedger Nano Sでは署名対象データはハッシュ値のみが表示され、署名対象がブラックボックスになってしまうためです。(フロントエンドで署名対象メッセージとそのハッシュ値を併記していれば少しマシな気がするかもしれませんが、ハッシュ値だけがすり替えられたトランザクションのものだったとしても人間には気づけません)

イーサリアムのスマートコントラクト呼び出しに署名するときはこのような画面になる

Bybit社内の署名手続きに(気の緩みなどから)不備があったのかもしれませんが、署名対象データの正確性を検証できなければそもそもHWWに画面がついている意味がありません。攻撃者はこれに気づいて、署名対象データを書き換える攻撃なら成功すると踏んだのでしょう。そして成功してしまいました。

読者の皆様はご存知かと思いますが、ビットコイン送金の場合は送金先アドレスと金額などが表示されるため、意図している送金と異なるものに署名する前に気づけるようになっています。また、技術力の極めて高いACINQ社(Phoenix Wallet)などは独自のLedger Nano用アプリを開発してライトニング対応させています。

莫大な金額をライトニングノードで運用するACINQ社は独自にLedger Nano用アプリを作成して署名対象データを正しく確認できるような運用になっている

いちビットコインユーザーとして取れる対策はあるのか

さて、ここまでを読んで勘のいい方なら気づいているかと思いますが、HWWによる一般的なビットコインの保管方法であればこの事件に使われた手法は有効ではなかったと考えられます。原因別に見ると:

Javascriptの差し替えによる不正トランザクションへのすり替え→WebベースのUIを使わない、OSSのウォレットを使うなどして多少なり軽減可能(前者で差し替えのルートを削減。後者は極論自分で全て監査できる)

署名対象データの不確認(Blind-signing)→画面のついたHWWで送金内容を確認してから署名することで対策可能。仮に不正トランザクションにすり替えられていてもここで検知すれば問題ない(ビットコインのHWWは一般的に生のトランザクションを受け取っているため、これが表示できる上に、署名対象データだけをすり替えられるおそれがない)

というわけで、定石に従ってビットコインを管理していれば良さそうです。ただし、もしカスタムのスクリプトでロックされているビットコインを送金する場合はHWWが送金内容の表示に対応していない可能性があるのでその点は追加の対策が必要かもしれません。(Ordinals Inscriptionsを扱ったり、Miniscriptを使った上級者向けプロダクトなどの場合が考えられます)

この場合取れる追加の対策としては、署名前のトランザクションを一旦エアギャップなどを介して信用できるデバイス(確実にマルウェアに侵されていない、オフラインのデバイス)に移して内容を確認することです。スクリプトの内容や画面に表示されるハッシュ値などに問題がなかった場合、そのままハードウェアウォレットで署名して、(心配ならもう一度信用できるデバイスで確認後)配信します。

ここでツッコミが入るかもしれません。DMMで盗られたのはビットコインだったじゃないか!と。こちらの事件に関しても、DMM側で実施された署名が何らかの理由で事実上Blind-signingになっていた可能性が指摘されています。原因が細かく公表されていないため議論の余地はありますが、やはり適切に定石に則ったビットコインの管理が行われていれば防ぐことができる流出だったのではないでしょうか。

Bybitの事件ではLedger Nano Sにおいてbが確認できないことが原因の1つとなった。ビットコインの場合は、一般的にHWW内でトランザクションから署名対象ダイジェストが生成される。

まとめ

・Bybitから2000億円分のETHが流出した事件の根本的原因はウォレットのWeb UI内のJavascriptが標的型攻撃用の悪意あるものにすり替えられていたことと、このJavascriptによって書き換えられたトランザクションデータをHWW側で視認できず、「Blind-signing(中身を確認せずに署名)」してしまったこと

・ビットコインの一般的なHWWは、生のトランザクションデータを受け取り、HWWの画面にその内容を表示し、署名対象のデータはHWW内で生成し署名するため、このようなすり替えに強い。ビットコイン保管の定石に従っていれば署名前にトランザクションのすり替えに気づける。

・ただし、カスタムのスクリプトを含むビットコイントランザクションに関してはHWWの画面に内容が表示されない可能性もあるため注意が必要である。使用予定の機種が対応しているか確かめるべきである。