Safeマルチシグ設定チェックリスト|オーナー・しきい値・ブラインド署名対策(2026)
チームやトレジャリー用にSafe(旧Gnosis Safe)マルチシグを設定する実務チェックリスト。オーナーとしきい値を適切に組み、Bybitから1500億円規模を奪ったブラインド署名の穴をふさぐ方法を解説します。
目次
- Safeマルチシグを、Bybitと同じ失敗を繰り返さずに設定するには?
- 1分要約
- どんな人向けか
- 結論
- 解説
- Safeのオーナー/しきい値モデルが実際に保証していること
- Bybit攻撃の仕組み
- 同じ穴は一般的な運用にもある
- 実務ガイド
- ステップ1:オーナーとしきい値を意図して設計する
- ステップ2:署名の前に、すべてのトランザクションを独立に検証する
- ステップ3:ハードウェアウォレットがクリア署名かブラインド署名かを確認する
- ステップ4:役割と端末を分離する
- ステップ5:モジュールとガードは追加前にレビューする
- ステップ6:リカバリー手順は必要になる前にリハーサルしておく
- ステップ7:本番投入前に小額でテストする
- ありがちな落とし穴
- チェックリスト
- FAQ
- 1. しきい値を上げれば(例:4-of-7)、Bybit型の攻撃を防げますか?
- 2. この事件のせいで、Safeはシングルキーのハードウェアウォレットより安全性が低いのですか?
- 3. 単純な送金も含めて、すべてのトランザクションでsafe-tx-hashes-utilのようなツールが必要ですか?
- 4. 見覚えのないModuleがSafeに接続されているのを見つけたら、どうすればいいですか?
- 参考資料
- 内部リンク
- 免責事項
Safeマルチシグを、Bybitと同じ失敗を繰り返さずに設定するには?
1分要約
- Safeのマルチシグは、設定しただけでは単一鍵のリスクを消しません。各署名者が、自分が何に署名しているかを独立した手段で確認して初めて機能します。
- 2025年2月、攻撃者はSafeの暗号署名の仕組みを破らずに、Bybitのマルチシグから約1500億円規模を抜き取りました。Safe{Wallet}の開発者端末を侵害し、署名者のブラウザに改ざんしたトランザクション情報を表示させ、ハードウェアウォレットがハッシュしか表示しなかったため、署名者は本当の送金先とcalldataを見ないまま承認してしまいました。
- しきい値の設計、独立したハッシュ検証、ハードウェア側でのクリア署名は、別々のオプションではなく1つのコントロールとして扱ってください。3-of-5を正しく組んでも、全員が同じUIを信じていれば、1回の誤承認で資金は全部抜かれます。
どんな人向けか
- チームのトレジャリーやDAO、共同管理ウォレット用にSafe(旧Gnosis Safe)を設定する人
- 金額をざっと見て「Confirm」を押す運用になっている署名者
- 既存Safeのオーナー構成・しきい値・モジュール・署名フローを点検するセキュリティ担当者
結論
Safeマルチシグのセキュリティモデルは、「各署名者が、同じインターフェースを信じなくても済む情報をもとに、自分が署名する内容を独立に確認する」という前提の上に成り立っています。Bybitの事件で壊れたのは、この前提であって、M-of-Nの署名スキーム自体ではありません。Safe{Wallet}のフロントエンドに仕込まれた不正なコードが、Bybitの署名者には通常の送金に見える画面を表示する一方、実際に実行されるトランザクションはSafeのロジックコントラクトを書き換え、攻撃者に制御を渡すものでした。承認した署名者は全員、画面の指示どおりに動いただけです。
改ざんされたフロントエンドを経由しても耐えられるSafe設定には、次の4つが必要です。
- オーナーとしきい値:1台の端末、1つのブラウザプロファイル、1人の人間だけでは必要な署名数に届かない構成にする。
- 独立したトランザクション検証:これから署名しようとしているブラウザタブとは別の経路で、
safeTxHash(ドメインハッシュ+メッセージハッシュ)を計算し直す。 - ハードウェアウォレットでのクリア署名:単純なETH送金以外では、ハッシュだけでなく実際の送金先とcalldataを表示できる端末を使う。
- モジュールとdelegatecallの管理:オーナーの署名フローを迂回できるものは、個別のレビューなしに追加しない。
解説
Safeのオーナー/しきい値モデルが実際に保証していること
Safeはオーナーアドレスの配列と threshold(uint256)を保持します。トランザクションを実行するには、Safeコントラクトが同一のトランザクションハッシュに対してthreshold件以上の有効なオーナー署名がそろっていることを確認し、execTransactionを呼び出します。よくある構成は、個人や小規模チームなら2-of-3(鍵を1つ失っても資金がロックされず、1つ侵害されても資金は抜かれない)、トレジャリーやDAO、ファミリーオフィスなら3-of-5以上(鍵を2つ失っても耐えられ、資金を動かすには3つの侵害が必要)です。
このモデルが保証するのは、「threshold件未満の異なる署名では資金を動かせない」という点だけです。「署名者が、自分が何に署名しているかを理解していた」ことは保証しません。署名の検証とトランザクションの理解は別の問題で、Bybitへの攻撃はまさに後者を狙ったものでした。
Bybit攻撃の仕組み
2025年2月21日、Bybitのコールドウォレット(Safeマルチシグ)から約1400〜1500億円相当が流出しました。これは現時点で史上最大規模の暗号資産盗難です。Safe自身のインシデントレポート、Bybitが依頼したSygniaのフォレンジック調査、Blockaid・NCC Groupによる分析など、複数の独立した事後検証が、ほぼ同じメカニズムを指摘しています。
- 攻撃者はSafe{Wallet}の開発者端末を侵害し、そのアクセス権を使ってSafeフロントエンドのAWSインフラに不正なJavaScriptを注入しました。対象はBybitの特定のSafeアドレスに限定されていました。
- Bybitの担当者がSafe UI上でマルチシグからウォームウォレットへETHを送る通常のトランザクションを開いたところ、改ざんされたフロントエンドはその普通の送金に見える画面を表示していましたが、実際に組み立てられていたトランザクションは、Safeの
masterCopy(実装コントラクト)ポインタを書き換える不正なコントラクトへのdelegatecallで、トランザクション実行の制御を攻撃者に渡すものでした。 - 署名者はLedgerのハードウェアウォレットで承認していました。当時のLedger Ethereumアプリは、
delegatecallを伴うSafeのexecTransaction呼び出しのcalldataを完全にはデコードして表示できず、ハッシュのみを表示していました。署名者には、ブラウザに表示された送金と実際に承認しているトランザクションが違うことを、端末側で確認する手段がありませんでした。 - フロントエンドとハードウェアウォレットの表示が食い違わなかった(どちらも通常の送金に反する表示をしなかった)ため、複数の正規オーナーがSafeを空にするトランザクションに署名してしまいました。
しきい値は、実在するオーナーが実際の鍵で満たしています。攻撃が成功したのは、そのオーナーたちに「自分が何に署名していると信じ込ませるか」を丸ごとコントロールされたからです。
同じ穴は一般的な運用にもある
このパターンはBybitの事件に限りません。署名者が「Webの画面に表示されたもの」だけを頼りにしているワークフローには、使っているマルチシグ製品を問わず同じ穴があります。特に設計段階で潰しておくべき失敗モードは次のとおりです。
- ハードウェアウォレットでのブラインド署名:単純なネイティブ送金以外で、端末がデコード済みのフィールドではなくハッシュしか表示しない場合、それはソフトウェアウォレットを信頼しているだけで、検証にはなっていません。
- UIの信頼源が1つしかない:全オーナーが同じWebアプリ、同じブラウザ拡張、あるいは同じコードのフォークから署名している場合、サプライチェーンを1回侵害するだけで、全員に同時に同じ偽トランザクションを見せることができます。
- delegatecallとモジュール経由のトランザクション:
delegatecallはSafe自身のストレージ文脈で実行され、オーナー・しきい値・実装コントラクト自体を書き換えられます。Safe Moduleは、一度追加すると自身のロジック次第でオーナーの署名フローを一切経由せずにトランザクションを実行できます。どちらも「金額が合っているか」だけでは足りない精査が必要です。
実務ガイド
ステップ1:オーナーとしきい値を意図して設計する
- 各オーナーの鍵は、別々のハードウェアウォレットに、別々の人が、別々の端末で保持します。1人が「便宜上」必要な署名を2つ以上持つ状態を作らないでください。
- 小規模チームや個人のトレジャリーなら、2-of-3が妥当な初期値です。鍵を1つ失っても資金はロックされず、1つの侵害だけでは資金を動かせません。
- DAOのトレジャリー、会社の資金、重要と呼べる規模の資産には3-of-5以上を使い、可能であればオーナーを異なる組織、少なくとも異なる物理拠点に分散させます。
- 各鍵を誰が持ち、インシデント時にどう連絡を取るかを、必要になる前に文書化しておきます。
ステップ2:署名の前に、すべてのトランザクションを独立に検証する
Safe Webアプリを「これから署名する内容の正解」として扱わないでください。別の経路でトランザクションハッシュを計算し直し、ハードウェアウォレットの表示と突き合わせます。
Safeチーム自身が公開しているトランザクション検証ガイドは、手動での方法を示しています。Safe Transaction Service APIから保留中のトランザクションを取得し、同じパラメータをブロックエクスプローラー上でSafeコントラクトのgetTransactionHashビュー関数に入力し、その結果を端末が表示するハッシュと比較します。
より速く、スクリプト化できる方法としては、safe-tx-hashes-utilのような独立したオープンソースツールがあります。Safe Transaction Serviceに直接問い合わせ、EIP-712のドメインハッシュとメッセージハッシュをローカルで計算するため、Safe UIを描画しているのと同じコードパスを信頼せずに済みます。
./safe_hashes.sh --network arbitrum --address 0x111CEEee040739fD91D29C34C33E6B3E112F2177 --nonce 234
公開されている出力例には、ドメインハッシュ、メッセージハッシュ、Safeトランザクションハッシュに加えて、デコードされたto・value・data・operationが含まれます。
Domain hash: 0x1cf7f9b1efe3bc47fe02fd27c649fea19e79d66040683a1c86c7490c80bf729
Message hash: 0xd9109ea63c50ecd3b80b6b27ed5c5a9fd3d546c2169dfb69bfa7ba24cd14c7a
Safe transaction hash: 0x0cb7250b8becd7069223c54e2839feaed4cee156363fbfe5dd0a48e75c4e25b
承認する前に、この3つの値をすべてハードウェアウォレットやMetaMaskの表示と突き合わせてください。一致しない場合、今見ている画面と実際に実行されるトランザクションが違うということです。その場で止めて調査し、「とりあえず署名して様子を見る」ことはしないでください。
ステップ3:ハードウェアウォレットがクリア署名かブラインド署名かを確認する
- 手元の端末のファームウェアが、承認しようとしている呼び出し(単純な送金、
execTransaction、delegatecall)を人間が読めるフィールドにデコードして表示するのか、それともハッシュしか出さないのかを確認します。 - ネイティブトークン送金以外でハッシュしか表示されない場合、そのトランザクションは端末単体では検証不能だと考え、ステップ2の独立したハッシュ比較を実質的なコントロールとして使ってください。
- 大きい、あるいは普段と違うトランザクションの前にはファームウェアを更新しておきます。スマートコントラクト呼び出しに対するクリア署名の対応範囲は、Bybitの事件以降、主要なハードウェアウォレットで広がってきていますが、端末や個別のコントラクト呼び出しの形によって対応状況は今も異なります。
ステップ4:役割と端末を分離する
- トランザクションの提案は1台の端末・セッションから行い、承認は別の端末・別のネットワークにいるオーナーに求めます。1台の感染した端末が、提案から承認の取りまとめまで両方できてしまう構成は避けてください。
- 署名に使う端末には、不要なブラウザ拡張を入れないでください。拡張機能が侵害されると、Safe固有の脆弱性がなくても、Webウォレットの表示内容を操作されます。
- 署名専用のワークステーションを用意している場合は、用途を限定し、一般的なブラウジングやメールクライアントを入れないようにします。
ステップ5:モジュールとガードは追加前にレビューする
- 現在Safeに接続されているすべてのModuleとGuardを一覧化します。Moduleは自身のロジック次第でオーナーの署名フローの外からトランザクションを実行でき、Guardは実行前にトランザクションをブロックまたは変更できます。
- 新しいモジュール(セッションキー用モジュール、リカバリーモジュール、自動化用の連携など)を追加する前に、ソースコードを読み、監査済みであることを確認し、オーナーの署名なしに何ができるのかを正確に把握します。
- 使っていないモジュールは外します。トレジャリーウォレットに、使っていない攻撃対象を残しておく理由はありません。
ステップ6:リカバリー手順は必要になる前にリハーサルしておく
- 侵害または紛失したオーナー鍵をローテーションする手順(
swapOwner、あるいはremoveOwnerとaddOwnerWithThresholdの組み合わせなど)を確認します。この操作自体も残りのオーナーからthreshold件の署名を必要とするため、鍵を1つ失う場合だけでなく、定足数を失いかけている場合の対応も計画しておきます。 - 鍵が侵害された疑いが出た場合に、誰に、どの順番で連絡するかを、特定の1人の記憶だけに頼らない形で書き残しておきます。
ステップ7:本番投入前に小額でテストする
- 新しく設定したSafeにトレジャリー規模の資金を移す前に、小額で一連の流れを最初から最後まで通します。提案、独立したハッシュ検証、各オーナーの端末でのクリア署名(またはフォールバックのハッシュ比較)の確認、承認、実行までです。
- 実行後のトランザクションをブロックエクスプローラーで確認し、UIが後から表示した内容ではなく、各オーナーが検証した内容と一致していることを確かめます。
ありがちな落とし穴
- 高いしきい値(例:4-of-7)だけで十分だと考え、全オーナーが同じWebアプリから独立検証なしに署名している
- 「金額が合っているから」という理由だけで、対象コントラクトやoperationの種類を確認せずに
delegatecallやモジュール経由のトランザクションを承認する - 設定作業中に1人が複数のオーナー鍵を「一時的に」保持し、そのままローテーションし忘れる
- ハードウェアウォレットがスマートコントラクト呼び出しでハッシュしか表示しないのに、それを意味のある確認として扱い、独立に計算した値と突き合わせない
- 工数を節約するために、監査されていない、あるいは素性のわからないモジュールやガードを追加する
- リカバリー・ローテーションの手順書を、特定の1人の記憶だけに頼って保管する
- 小額でのテストトランザクションを省略し、初めてのプロセス確認を大きな送金で行う
チェックリスト
- [ ] オーナー鍵は別々のハードウェアウォレットに、別々の人が、別々の端末で保持している
- [ ] しきい値がウォレットの用途に合っている(個人・小規模チームなら最低2-of-3、トレジャリーなら3-of-5以上)
- [ ] しきい値に単独で届くほど多くの鍵を持つ人がいない
- [ ] 署名前に、すべてのトランザクションの
safeTxHash(ドメインハッシュ+メッセージハッシュ)をSafe Webアプリとは別の経路で計算し直している - [ ] 署名に使うハードウェアウォレットが実際に送信するトランザクション種別をクリア署名できるか確認済み、できない場合は独立したハッシュ検証に頼っている
- [ ] 提案と承認を別々の端末・ネットワークで行い、1台が提案と承認の取りまとめを両方できる構成になっていない
- [ ] 接続済みのModuleとGuardをすべて棚卸しし、監査済みプロジェクト由来であること、オーナー署名なしに何ができるかを確認している
- [ ] 鍵のローテーションとインシデント対応の手順が、特定の1人の記憶に頼らず文書化されている
- [ ] Safeに重要な資金を入れる前に、ハッシュ検証を含む一連の流れを小額でテスト済み
- [ ] 署名用ハードウェアウォレットのファームウェアが最新である
FAQ
1. しきい値を上げれば(例:4-of-7)、Bybit型の攻撃を防げますか?
それだけでは防げません。しきい値を上げると、だますべき人数が増えるためハードルは上がりますが、全員が同じ侵害されたインターフェースの表示を根拠に承認しているなら、攻撃者は同じ偽のトランザクションでより多くの人をだませばよいだけで、誰か1人が気づく保証にはなりません。実際に気づけるのは、独立した検証です。
2. この事件のせいで、Safeはシングルキーのハードウェアウォレットより安全性が低いのですか?
いいえ。壊れたのはSafeプロトコルの署名検証ではなく、人間向けにトランザクションを表示するフロントエンドです。同じリスクは、Webインターフェースだけをトランザクション表示の頼りにしているマルチシグやシングルキーウォレットすべてに存在し、シングルキーウォレットにはそもそもしきい値という後ろ盾がありません。対策はマルチシグをやめることではなく、検証を運用に組み込むことです。
3. 単純な送金も含めて、すべてのトランザクションでsafe-tx-hashes-utilのようなツールが必要ですか?
コントラクト呼び出しを伴わない単純なネイティブトークン送金は、多くのハードウェアウォレットが送金先と金額を端末上で完全にクリア署名できるため、相対的にリスクは低いです。独立したハッシュ検証は、コントラクトとのやり取り、delegatecallトランザクション、モジュールの変更、ハードウェアウォレットがハッシュしか表示しないケースに絞って使ってください。
4. 見覚えのないModuleがSafeに接続されているのを見つけたら、どうすればいいですか?
侵害の可能性があるものとして扱ってください。何をするモジュールか理解する前に慌てて削除しないでください。リカバリー用やセッションキー用のモジュールは、削除すると正規の機能が止まる場合があります。ただし、可能であれば直ちにそれをトリガーできる経路を制限し、それ以上トランザクションを実行する前に全オーナーでレビューしてください。
参考資料
- Safe: what is a Safe smart account(Safe Docs)
- Safe: smart account signatures(Safe Docs)
- Verify Safe transactions(Safeチーム、HackMD)
- safe-tx-hashes-util(pcaversaccio、GitHub)
- In-Depth Technical Analysis of the Bybit Hack(NCC Group)
- How to Prevent the Next $1.5B Bybit Hack: A Strategic Approach to Solving Blind Signing(Blockaid)
内部リンク
免責事項
投資助言ではありません。一般的なセキュリティ情報の提供のみを目的としています。マルチシグの設定、ハードウェアウォレットのファームウェアの挙動、モジュールのエコシステムは頻繁に変わります。重要な資金を扱う前に、利用しているSafeのバージョン、ネットワーク、署名用ハードウェアで現在の挙動を必ず確認してください。