メインコンテンツへスキップ
セキュリティ事件の技術解説
セキュリティ
暗号資産
アーキテクチャ設計
認証・認可
信頼性
決済

Binance 63億ドル流出(2026年10月)の技術解説 — 秘密鍵を守っても資産は出ていく。署名パイプラインを守る出金ポリシーの設計

2026年10月29日のBinanceホットウォレット流出(約63億米ドル)を公式発表とオンチェーン記録で整理し、秘密鍵の保護と『何に署名させるか』の認可が別問題である理由を、EIP-7702の委任署名と、テスト済みの出金ポリシーエンジンで解説します。

公開日
読了時間
29分
著者
友田 陽大
シェア
目次

2026年10月29日、世界最大級の暗号資産取引所 Binance のホットウォレットから、約63億米ドル相当の資産が流出しました。Binance自身の発表では、侵害は協定世界時(UTC)の20時05分ごろ、日本時間では10月30日の5時05分ごろに始まっています。

この記事は事件の経緯を整理したうえで、多くの解説が触れていない一点を掘り下げます。秘密鍵を安全に保管していても、資産は出ていきうるということです。

鍵を守る仕組み(HSM・MPC・KMS)が守るのは「鍵を盗ませないこと」です。「いま署名しようとしているものが、正当な出金か」を判断するのは、別の層の仕事です。オンチェーンに残った記録は、その別の層が問われた可能性を示しています。その記録と、送金・決済のシステムを作る側が取るべき設計を、テストで動作を確かめたコードで示します。

情報の時点と扱い: 本記事は2026年11月1日1時(日本時間)までに確認した一次資料に基づきます。Binanceは技術的なポストモーテムをまだ公表しておらず、根本原因は確定していません。以下では、公式発表で確認できる事実、調査会社の分析(報道・仮説)、筆者の推論を書き分けます。構成図とコードは一般化した参照モデルで、Binanceの内部構成を復元したものではありません。教材のコードは、実運用の資産管理システムとして使えるものではありません。

30秒で分かる要点

  • 何が起きたか: Binanceのホットウォレット(インターネットにつながり、即時の出金に使う財布)が侵害され、約63億米ドル相当が流出した。対象は10前後のチェーンにわたる。
  • 原因は確定していない: 初報は「DevOpsエンジニアのノートPCが侵害され、攻撃者がサービスコンテナに入り、不正な出金トランザクションを送った可能性」を挙げた。同日の第2報は、その後の調査で、ほかにも侵入箇所が見つかったと修正した。
  • 秘密鍵: Binanceは「現時点で漏えいの証拠は見つかっていない」とする。証拠がないことは、漏えいがなかったことの証明ではない。
  • お金の状態は3種類: 約30億ドルが発行体によって凍結された。Binanceは自社資金で流出分の90%を補填した。犯人からの回収額は公表されていない。
  • 利用者への影響: 出金は停止中で、11月1日に段階的に再開する予定。入金は通常どおりとされる。

本番の顧客データを預かる前に

Webアプリ・SaaS のセキュリティ監査 — 認可・テナント分離・設定まで、コードを読んで確かめます

公式発表で確認できる事実と時系列

Binanceは事件について3本の公式発表を出しています。発表ページはJavaScriptで描画されるため、同社のお知らせAPIが返す本文と、公開・更新の時刻(UTC)で照合しました。

時刻(UTC)日本時間出来事根拠と分類
10/28 午前10/28攻撃者の運用ウォレットに Tornado Cash 経由で資金が入るCointegrity の分析(報道)
10/29 20:05ごろ10/30 05:05ごろホットウォレットの侵害が始まる。最初の流出は XRP LedgerBinance 第2報(確認済み)。チェーンは Cointegrity
10/29 20:20:5910/30 05:20:59ホットウォレット「Binance 14」にEIP-7702の委任が設定されるオンチェーン(確認済み。後述)
10/29 21:01ごろ10/30 06:01ごろTether が主な受け取りウォレットを凍結Cointegrity(報道)
10/29 22:27〜22:33ごろ10/30 07:27〜07:33ごろ出金を停止Cointegrity(報道)。停止の事実は第1報で確認
10/29 23:5610/30 08:56Binance 14 に入った入金が最後に吸い上げられるElliptic(報道)
10/30 02:2310/30 11:23第1報。ノートPCの可能性、鍵の漏えいの証拠なし、約30億ドル凍結Binance(確認済み)
10/30 11:3610/30 20:36第1報を更新。「入金は影響を受けておらず通常どおり」と明記Binance(確認済み)
10/30 19:3310/31 04:33第2報。20:05の開始時刻、約63億ドル、ノートPC説の修正、80%を補填Binance(確認済み)
10/31 14:2410/31 23:24第3報。補填90%、準備金の証明(PoR)のスナップショット、出金は11/1再開予定Binance(確認済み)

初報から第2報で変わったこと

最も重要な変更は、侵入経路の説明です。第1報はこう書いています。

initial investigation suggests that the security incident may involve a compromised DevOps engineer's laptop, which allowed an attacker to gain access to a service container and submit unauthorized withdrawal transactions.

この時点でも「may involve(関係している可能性がある)」という慎重な書き方です。第2報は、この説明自体を修正しました。

Our initial investigation suggested that the incident may involve a compromised laptop, however, our subsequent investigation has uncovered additional points of breach.

「ほかの侵入箇所」が何かは公表されていません。初報だけを引用して「原因はDevOpsのノートPC」と書いた記事は、すでに古い情報に基づいています。

「凍結」「回収」「補填」は別物

報道で混同されやすい3つの言葉を整理します。

状態意味金額誰のお金で、どこにあるか
凍結(Frozen)発行体(Tether・Circle等)が、攻撃者のアドレスにあるトークンを動かせなくしたBinance発表で約30億ドル。Ellipticは28.5億ドル(盗難額の44%)、TRMは約27億ドル攻撃者のアドレスに残ったまま。戻ってはいない
回収(Recovered)盗まれた資産そのものが取り戻された公表なし—
補填(Replenished)Binanceが自社の資金で、流出した資産と同じ銘柄を用意した流出額の90%(第3報)。主要10銘柄は100%自社の財務・SAFU(利用者保護基金)・先物保険基金

凍結が効いたのは、ほぼUSDTとUSDCだけです。Ellipticは「ビットコイン、XRP Ledger、Solana、NEAR上で盗まれたものは凍結されていない」と書いています。中央の発行体を持つトークンは止められても、ネイティブな資産は止められない、というブロックチェーンの性質が表れています。

秘密鍵についての公式見解

第1報は「We have found no evidence of any wallet private key leak.」、第2報は「At this stage, we have found no evidence that wallet private keys were leaked.」と書いています。第2報では「At this stage(現時点で)」が加わりました。

これは「漏えいしていない」という断定ではありません。後述するオンチェーンの記録は、Binanceの署名システムが、攻撃者の求める署名を生成させられたという見方と矛盾しません。ただし、それだけでは、鍵が持ち出されたかどうかを決められません。

まだ分かっていないこと

  • 根本原因と、第2報の言う「ほかの侵入箇所」
  • 鍵が持ち出されたのか、署名のサービスが悪用されたのか
  • 攻撃者が、後述する50件の事前署名済みの委任をどう入手したか
  • 10月30日0時台(UTC)に入金も一時停止したという報道の真偽(Binanceの公式ページは「入金は影響を受けていない」と更新している)
  • 補填資金の内訳(SAFU・保険基金・財務の比率)
  • 犯行の主体。TRM Labs は北朝鮮の TraderTraitor による犯行と「高い確度で」評価し、Elliptic も「可能性が高い」とする。Binance自身は特定しておらず、政府による帰属の発表も確認できない。これは調査会社の評価であり、確定した事実ではない

基礎知識: 秘密鍵を持つことと、署名させられることは違う

ここから技術の話に入ります。先に、非エンジニアの方にも必要な前提を二つだけ押さえます。

ホットウォレットとコールドウォレット

ホットウォレットは、ネットワークにつながっていて、出金の要求に自動で応じられる財布です。利用者の出金を数秒から数分で処理するために、取引所はある程度の資産をここに置きます。

コールドウォレットは、ネットワークから切り離された環境に鍵を置く財布です。安全な代わりに、資金を動かすには人手と時間がかかります。

取引所の設計は「ホットウォレットにどれだけ置くか」「コールドからどう補充するか」の兼ね合いです。今回の標的はホットウォレットで、それでも被害額が63億ドルに達したことは、取引所の規模の大きさを示しています。

実印と、金庫番のたとえ

ブロックチェーン上の送金は、「秘密鍵による署名」で正当性が決まります。たとえるなら、秘密鍵は会社の実印です。

実印を頑丈な金庫(HSMなど)にしまい、持ち出せなくしても、金庫番に「これに押してください」と書類を渡せる立場を奪われれば、書類には押印されてしまいます。しかも、金庫番が書類の中身を読まずに押す運用なら、書類が「送金依頼」でも「委任状」でも押されます。

このたとえには限界があります。現実の押印は人が内容を読みますが、署名のシステムは、何を見て押すかを、設計した人が決めた規則どおりにしか判断しません。その規則が「金額と送金先だけを見る」だったとき、金額も送金先もない種類の書類が来たら、規則の外にあります。

守る層は三つある: 鍵・署名・業務

「資産を守る」は、少なくとも三つの別の問いに分かれます。

層問い守る仕組みの例破られると
1 鍵の保管鍵を持ち出せるかHSM、MPC、KMS鍵が盗まれ、攻撃者が自分で署名できる
2 署名の認可何に署名してよいかポリシーエンジン、署名内容のデコード、承認フロー正規の署名システムが、望まない署名をする
3 業務の認可その出金は業務として正当か出金先の許可リスト、限度額、独立承認、異常検知署名は正しい形でも、正当でない資金移動が通る

多くの議論は、層1に集中します。鍵を守る設計は成熟しており、NIST SP 800-57のような標準もあります。しかし、層1だけでは、層2と層3は守れません。今回のように、層1が(公表の範囲では)破られたかどうか不明なまま、巨額の資金が出ていく事態が起こりえます。

HSM・MPC・KMSは何をして、何をしないか

仕組み役割しないこと
HSM(専用の耐タンパ装置)鍵を装置の外に出さず、装置の中で署名する署名の要求の中身が正当かは判断しない。呼び出せる権限を持つ者の要求には応じる
MPC(鍵を分割して共同で署名)一か所が破られても、鍵全体は盗まれない参加者の過半が同じ要求に同意すれば署名する。要求の中身の正しさは別の問題
KMS(クラウドの鍵管理)鍵の保管・権限管理・使用の記録IAMの権限を持つ主体が署名APIを呼べば署名する

共通するのは、「誰が署名を依頼できるか」と「何に署名してよいか」を、鍵の仕組みは決めてくれないことです。これは、層2の設計の責任です。

オンチェーンで見えたこと: 金額も送金先もない署名

ここは、公開されている記録で、誰でも確認できる範囲の話です。

確認できた事実

Etherscanに公開されている、2026年10月29日20:20:59(UTC)のトランザクションは、ブロック26,300,753に含まれ、次の特徴を持ちます。

  • トランザクション種別は4(EIP-7702 の「コード設定」型)
  • 送信元は攻撃者のものとラベルされたアドレス、宛先は「Binance 14」とラベルされたBinanceのホットウォレット
  • 50件の認可(authorization)が含まれる。そのうち有効なのは1件(nonce 18914809)で、委任先のアドレスは1つ

筆者は、公開のEthereum RPCから同じトランザクションを取得し、上記の内容(種別4、50件の認可、チェーンID 1、委任先アドレス1つ)を自分で確認しました。

筆者の観測: 同じRPCで「Binance 14」の現在のコードを確認すると、2026年11月1日の時点で空(0x)でした。これは、現時点では委任が設定されていない(解除されたか、設定が置き換わった)ことを示しますが、いつ・誰が解除したかは確認していません。

EIP-7702とは何か(仕様に書かれていること)

EIP-7702は「Set Code for EOAs」という提案で、ステータスは最終(Final)です。通常、暗号資産のアカウント(EOA)は、鍵で署名して送金するだけで、プログラムを持ちません。EIP-7702は、EOAが、指定したコントラクトのコードを自分のものとして動かせるようにする仕組みです。仕様の要点は次のとおりです。

  • 署名の対象は [chain_id, address, nonce] の3つで、送金額や送金先は含まれません
  • 認可が有効なら、そのアカウントのコードに 0xef0100 || address(「このアドレスのコードに委ねる」という印)が書かれる
  • 以後、そのアカウントへの呼び出しは、委ねられた先のコードが、そのアカウントの立場で実行される
  • トランザクションの実行が失敗しても、設定された委任は巻き戻されない

仕様の「セキュリティ上の考慮」節は、委任先のコードの設計が悪いと、「悪意のある者が、署名者のアカウントをほぼ完全に制御できる」と明記しています。

何が言えて、何が言えないか

言えること(確認済み)言えないこと
Binance 14 に、EIP-7702の委任が設定された記録がある攻撃者がどうやってその署名を入手したか
委任の認可は、そのアカウントの鍵で署名されている必要がある(仕様)鍵が持ち出されたか、署名システムが署名させられたか
委任の署名は、金額・送金先を含まない(仕様)Binanceの署名システムが、この種の署名を検査していたかどうか(内部構成は非公開)

調査会社のEllipticは、攻撃者が「Binanceの自分のシステムに署名させたように見える」と分析し、Binance側の説明として、この委任が「通常の承認の管理を経なかった」と伝えています。TRM Labsも「ホットウォレットの署名インフラの侵害を指している」と述べます。ただし、これらは分析であり、Binanceの公式な原因の認定ではありません。SlowMistなど、鍵の漏えいの可能性を仮説に残す専門家もいます。

筆者の見解: なぜ「金額と送金先だけ」を見るポリシーは足りないのか

以下は、公表された事実からの筆者の推論です。確定した事実ではありません。

出金のポリシーを「金額が上限以内で、送金先が許可リストにある」と作ると、送金の形をしていない署名(アカウントの動作を変えるもの)は、そもそも判定の対象外になりえます。ポリシーが「送金か、送金でないか」を区別せず、署名する実バイト列を読まない設計だと、この穴が開きます。

今回、Binanceのポリシーがどうだったかは不明です。ただ、設計者が学べるのは、「許可する署名の種類を限定する」という原則です。後述の教材で、これをコードにします。

参照アーキテクチャ: 出金・署名パイプライン

注意: 下の図は、取引所・決済システムの一般的な参照モデルです。Binanceの内部構成を復元したものではありません。

 [利用者]──出金要求──▶ [出金API] ──▶ [ポリシーエンジン] ──▶ [署名サービス] ──▶ [ブロックチェーン]
                         認証・冪等      層2・層3の判定         層1(HSM/MPC/KMS)
                         キー受付        ・署名する実バイト列    鍵は外に出ない
                                         をデコード
                                         ・送金以外は拒否
                                         ・限度額を原子的に予約
                                         ・承認(独立2名)を検証
                                  │
        [DevOps端末] ─ ─ ✕ ─ ─ ▶ 本番の署名経路へ直接つながない(人は、承認の画面だけ)
                                  │
                                  ▼
                        [監査ログ(追記のみ)] ──▶ [異常検知・緊急停止]

脅威モデル: アカウントの侵害から不正出金につながる経路

段階起こること止める層
1. 足がかり開発者の端末・CI・コンテナなどが侵害される端末の分離、短命の認証情報、ネットワークの分離
2. 横展開侵害した主体が、署名サービスを呼べる権限に到達するIAM・ワークロードのIDの最小権限、署名サービスの呼び出し元の限定
3. 署名の要求攻撃者が、署名を求める層2: 署名する実バイト列の検査、送金以外の既定拒否
4. 資金の移動署名が通れば、資産が動く層3: 出金先の許可、限度額、独立承認、冷却期間
5. 持ち去り資産が出ていき、分散する異常検知、緊急停止、発行体との連携(凍結)

DevOps端末から本番へ: 信頼境界

ただし、第2報で説明は修正され、実際の経路は不明です。第1報が挙げた「DevOps端末→サービスコンテナ→出金」という経路が仮にそのとおりだとすれば、それは人の端末が、本番の資産に近すぎる設計の典型的なリスクにあたります。一般に、次を分けます。

  • 開発・運用の端末は、本番の署名経路に直接つながない。必要な操作は、承認フロー(変更管理)を経る
  • サービスの権限(ワークロードID)は、そのサービスの役割だけに絞る。コンテナに、出金を指示できる権限を持たせるなら、そのコンテナを乗っ取った者も同じ権限を得る
  • 人が持つ長期の認証情報を、本番の署名のAPIに通用させない。短命のトークンと、都度の承認を使う

教材: 署名の前に置く出金ポリシーエンジン

ここから、層2・層3をTypeScriptで実装した教材を示します。コードの全文とテストは、このサイトのリポジトリの tests/unit/fixtures/withdrawal-policy.ts と tests/unit/withdrawal-policy.test.ts にあり、CIで常に実行されます。

限界の明示: これは教育用の参照実装です。実運用の資産管理システムには、永続化されたデータベース、署名サービスとの認証、鍵の運用、監査、障害対応が必要で、この教材はその代わりになりません。

設計の方針

要件この教材での実装
通貨と最小単位を明示した金額型Money { asset, minor: bigint }。"0.1" のような文字列から、丸めずに整数へ変換。小数が多すぎれば拒否
浮動小数点誤差の回避金額は常に整数(bigint)。number を使わない
署名する実バイト列の判定呼び出し元の申告ではなく、バイト列をデコードして種類を判断
送金以外の署名の拒否委任(種別4)・承認(approve)・未知のものは既定で拒否
不正な出金先の拒否許可リスト+追加後の冷却期間
承認の束縛・期限・リプレイ対策承認は要求のダイジェストに束縛され、期限を持つ。同じ要求IDの予約は一度きりで、承認済みの要求の使い回しは拒否
職務の分離要求者本人の承認は無効。異なる2名、異なる2つの役割が必要
原子的な限度額更新「確認」と「更新」を一つの不可分な操作にする
冪等性同じ冪等キーは同じ判断を返し、二重に予約しない。内容が違えば拒否
フェイルクローズ想定外のエラーは拒否に倒す
監査可能性すべての判断を、追記のみのログに残す
緊急停止サーキットブレーカー(開くと全拒否)。冪等性の保存済みの判断より先に判定するので、許可済みの要求の再送も止まる

署名する実バイト列をデコードする

export interface SigningPayload {
  readonly txType: number; // EIP-2718 のトランザクション種別。0x04 は EIP-7702
  readonly to: string;
  readonly valueWei: bigint;
  readonly data: string; // 16進のcalldata。ETHの単純送金は "0x"
}

export type Intent =
  | { readonly op: "native_transfer"; readonly recipient: string; readonly amount: bigint }
  | { readonly op: "erc20_transfer"; readonly token: string; readonly recipient: string; readonly amount: bigint }
  | { readonly op: "delegation" | "approval" | "unknown" };

const SELECTOR = {
  transfer: "0xa9059cbb", // transfer(address,uint256)
  approve: "0x095ea7b3", // approve(address,uint256)
  setApprovalForAll: "0xa22cb465", // setApprovalForAll(address,bool)
} as const;

/** 呼び出し元のラベルではなく、バイト列を読む。読めないものは "unknown"。 */
export function decodeIntent(p: SigningPayload): Intent {
  if (p.txType === 0x04) return { op: "delegation" }; // アカウントのコードを委ねる署名
  const data = p.data.toLowerCase();
  if (data === "0x") return { op: "native_transfer", recipient: p.to.toLowerCase(), amount: p.valueWei };
  if (p.valueWei !== BigInt(0)) return { op: "unknown" };
  const selector = data.slice(0, 10);
  if (selector === SELECTOR.approve || selector === SELECTOR.setApprovalForAll) return { op: "approval" };
  if (selector === SELECTOR.transfer && data.length === 10 + 64 + 64) {
    return {
      op: "erc20_transfer",
      token: p.to.toLowerCase(),
      recipient: "0x" + data.slice(34, 74),
      amount: BigInt("0x" + data.slice(74, 138)),
    };
  }
  return { op: "unknown" };
}

0xa9059cbb・0x095ea7b3・0xa22cb465 は、それぞれ ERC-20の transfer(address,uint256)・approve(address,uint256)・setApprovalForAll(address,bool) の関数セレクタで、筆者は公開のシグネチャ辞書で確認しました。

ポイントは、許可する種類を積極的に列挙し、それ以外を拒否することです。「危険なものを禁止する」方式(ブラックリスト)だと、知らない種類の署名がすり抜けます。

判定の順序と、「申告」と「実体」の突き合わせ

// 抜粋: WithdrawalPolicy.#decide
if (this.#circuitOpen) return audit(deny("circuit_open"));

// 署名される「実体」を判定する。申告ではない。
const intent = decodeIntent(req.payload);
const expectedToken = this.cfg.tokenContracts[asset]?.toLowerCase();
const kindOk =
  (intent.op === "native_transfer" && asset === "ETH") ||
  (intent.op === "erc20_transfer" && intent.token === expectedToken);
if (!kindOk) return audit(deny("operation_not_permitted"));
if (intent.recipient !== req.destination.toLowerCase() || intent.amount !== minor) {
  return audit(deny("payload_mismatch"));
}
// ...許可リスト・冷却期間・1回あたりの上限・承認の検証...
// 最後に、限度額の「確認と更新」を、一つの不可分な操作で行う:
const reservationId = `rsv_${req.id}`;
const slot = await this.store.tryReserve(reservationId, req.accountId, asset, minor, this.cfg.dailyLimit[asset], now);
if (slot === "duplicate") return audit(deny("request_already_used"));
if (slot === "limit") return audit(deny("daily_limit"));
return audit({ kind: "allow", reservationId });

要求が申告する金額と宛先が、署名される実体と一致するかを確かめるのが payload_mismatch です。申告された内容を信じないのが、層2の基本です。

承認は「特定の要求」に束縛する

export function requestDigest(r: WithdrawalRequest): string {
  const p = r.payload;
  const canonical = JSON.stringify([
    r.id, r.accountId, r.amount.asset, r.amount.minor.toString(), r.destination,
    p.txType, p.to.toLowerCase(), p.valueWei.toString(), p.data.toLowerCase(),
  ]);
  return createHash("sha256").update(canonical).digest("hex");
}

承認者が同意するのは「この要求」です。承認をダイジェストに束縛すれば、別の要求への流用(リプレイ)は無効になります。さらに、期限を持たせ、要求者本人の承認を無効にし、異なる2名・異なる2役割を要求します。

競合状態: 「確認してから更新」は破れる

限度額の確認を、次のように書くことがあります。

// 悪い例(RacyStore): 読む → 待つ → 判断する → 書く
const used = this.#used.get(key) ?? BigInt(0); // 1. 読む
await sleep(5);                                // 2. DBへの往復で待つ
if (used + amount > limit) return "limit";     // 3. 古い値で判断する
this.#used.set(key, used + amount);            // 4. 書く
return "reserved";

「読んでから書くまでの間に、別の要求が割り込む」ことをTOCTOU(確認時と使用時のずれ)と呼びます。具体的な数字で見ます。1日の上限が10 ETH、1件が0.9 ETHの要求が同時に50件届くとします。正しくは11件(10 ÷ 0.9 の切り捨て)で止まるはずです。

実装50件の同時要求のうち、通った件数
確認と更新を分けた実装(上の悪い例)50件(上限を大幅に超過)
確認と更新を一つの不可分な操作にした実装11件(正しく上限で止まる)

これは、筆者が実際にテストで測った値です。全件が通ったのは、50件すべてが「まだ誰も使っていない」という古い値で判断したためです。

実際のデータベースでは、UPDATE ... SET used = used + $amount WHERE used + $amount <= $limit のような条件つきの更新(更新された行数で成否を判断)、または行ロックで実現します。教材のメモリ上の実装は、「await を挟まずに読み書きする」ことで、同じ性質を示しています。予約には要求IDごとの一意制約(UNIQUE)も必要で、教材は同じ要求IDの二重予約を request_already_used として拒否します。承認済みの要求を別の冪等キーで再送しても、限度額を二重に使えません。

テスト結果

npx vitest run tests/unit/withdrawal-policy.test.ts の結果は25テストすべて合格(筆者の環境)、tsc の型検査とESLintも通りました。検証した項目は次のとおりです。

  • 金額の変換(小数が多すぎる・負・ゼロ・指数表記を拒否)
  • 署名のデコード(送金・委任・承認・未知)。ETH付きの呼び出し、途中で切れた・余分なバイトのあるcalldataは読み切れないので拒否。アドレスの大文字小文字は区別しない。USDTの要求にETH送金の署名は通らない
  • 許可リストにある宛先への少額の出金は許可(ETHとUSDT)
  • 委任・承認・偽のトークンの署名は、要求が無害に見えても拒否
  • 申告の宛先・金額と、署名の実体が違う要求を拒否
  • 未知の宛先、追加直後(冷却期間中)の宛先を拒否
  • 上限超過、承認が必要な額の承認なしを拒否
  • 承認の期限切れ、別の要求への流用(宛先・金額・アカウントのどれを変えても無効)、本人承認、同じ役割だけ、同一人の重複、1人が2つの役割を兼ねる承認を拒否
  • 承認済みの要求を、別の冪等キーで再送して二重に使うことを拒否(request_already_used)
  • 境界値(冷却期間・1回の上限・承認のしきい値・承認の期限がちょうどのとき)と、24時間のローリング窓(上限ちょうどまで使え、24時間後に解放される)
  • 冪等性: 同じ要求の再送は一度だけ予約。内容が違えば idempotency_conflict。一過性の障害は記憶されず、同じキーで再試行できる
  • 50件の同時要求で上限を超えない(原子的な予約)/確認と更新を分けた実装は超える
  • サーキットブレーカーの全拒否(すでに許可された要求の再送も止まる)と、判断のログの記録(変更不可)。監査ストアが落ちても遮断は開く
  • ストアの障害が拒否になる(フェイルクローズ)。予約の後で監査ログの書き込みが失敗した場合も拒否になるが、補償処理はないので予約は戻らない(既知の限界として固定)

テストを通すために、不変条件を弱めたり、テストを無効にしたりはしていません。

この教材が示さないこと

  • 実際の署名サービスとの接続、鍵の運用、ネットワークの認証
  • 永続化された、複数ノードにまたがる限度額の整合性
  • EIP-7702の署名そのものの検証(本教材は、署名される前の要求を判定する)
  • 異常検知の統計モデル(しきい値の設計)
  • 承認者の認証。approverId と role は検証済みの入力を前提にしており、承認の署名そのものの検証は含まない
  • 日次の累計に対する承認。承認のしきい値は1件ごとなので、小口に分割すれば承認を避けられる。実運用では累計にもしきい値を掛ける
  • 補償処理。予約の後で監査ログの書き込みが失敗すると、拒否を返すが予約は戻らない
  • 拒否された判断も、同じ冪等キーで保存される。内容を直した要求は、新しい冪等キーで送る

準備金の証明(PoR)で、何が確かめられるか

Binanceは第3報で、10月31日0時(UTC)時点の準備金の証明(Proof of Reserves)のスナップショットを示し、ゼロ知識証明を含む完全な証明を11月3日(UTC)までに公表予定としています。

筆者の理解では、PoRが示すのはある時点で、顧客の預かり資産に見合う資産があるかです。これが示さないことも、同じくらい重要です。

PoRで確かめられるPoRでは確かめられない
顧客の残高の合計に対して、保有資産が足りているかの時点の状態鍵や署名の管理が安全か
保有資産の一部が、公開のアドレスにあること資産がどう失われたか、再発しないか
(ゼロ知識証明を使う場合)顧客ごとの残高を開示せずに、総額の整合を示せること負債(顧客への債務)が、すべて含まれているか(設計次第)

PoRは、「いま足りているか」への答えで、「安全に守られているか」への答えではありません。両者を混同しないことが、取引所を評価するときの基本です。

経営層へ: 鍵を守ってもお金が出ていく理由と、決める順番

非エンジニアの方向けに、この事件から学べる判断を整理します。

3つの問い

  1. 金庫の鍵の管理は、誰が、どこまで? 鍵の保管(層1)は、専門の製品と手順で守れます。ここは、多くの企業が投資しています。
  2. 金庫番に「何を押してよいか」の規則は、誰が決めている? 層2です。規則が「金額と送金先だけ」だったり、規則を書いた人が退職していたりしませんか。
  3. お金が出ていくとき、人の目と、止める手段はあるか? 層3です。高額の出金は二人以上の独立した承認、異常があれば自動で止まる(サーキットブレーカー)、が基本です。

優先順位のつけ方

優先度行動目的
高本番の資金移動に使う認証情報・権限の棚卸し。人の端末から本番の署名経路に届くものを除く層2の入口を守る
高出金・送金の限度額と、独立承認の閾値を決める。決済・送金の機能を持つなら、同時実行でも上限が守られることを確認層3
中署名・承認・設定変更の監査ログを、改ざんされない場所に置く事後の検証
中緊急停止の手順を決め、訓練する被害の拡大を止める
低公開されたポストモーテムを読み、自社の差分を確認する学習

決済・送金を扱う事業では、「止まる」ことを機能として設計するのが経営判断です。サービスが止まるのは損失ですが、止められないまま資産が出ていくより小さい、という判断を、平時にしておく必要があります。

チェックリスト

設計・実装

  • 署名サービスは、呼び出し元の申告でなく、署名する実バイト列をデコードして判定している
  • 許可する署名の種類を列挙し、委任・承認・権限移譲・未知のものを既定で拒否している
  • 出金先は許可リストで、追加後に冷却期間がある
  • 承認は特定の要求に束縛され、期限を持ち、要求者本人は承認できない
  • 限度額の「確認と更新」が原子的で、同時実行のテストがある
  • 冪等キーをサーバー側で扱い、同じキーで内容が違えば拒否する
  • 想定外のエラーは拒否(フェイルクローズ)になる
  • 金額は整数の最小単位で持つ(浮動小数点を使わない)

運用・組織

  • 人の端末から、本番の署名経路へ直接届かない
  • サービスの権限(ワークロードID)は、役割だけに絞られている
  • 判断・承認・設定変更の監査ログが、追記のみで、別の場所に残る
  • 緊急停止の手順があり、訓練されている
  • 高額の出金に独立した複数の承認が要る(職務の分離)
  • オンチェーンとオフチェーンの残高の突き合わせを自動で行っている

現時点の結論と、今後の確認事項

  • 事実として言えること: ホットウォレットが侵害され、約63億米ドル相当が流出した。凍結は約30億ドル、補填は90%(Binance自身の資金)、回収は公表なし。出金は停止中で、11月1日に段階的に再開予定。オンチェーンには、EIP-7702の委任がBinance 14に設定された記録がある。
  • まだ言えないこと: 根本原因、鍵の漏えいの有無、攻撃者が委任の署名を得た方法、犯行の主体(調査会社の評価は仮説)。
  • 技術的な教訓: 秘密鍵の保護(層1)は、署名の認可(層2)と業務の認可(層3)の代わりになりません。何に署名してよいかを、実バイト列で判定し、既定で拒否する設計が、鍵の保護とは別に必要です。

今後確認すべきは、Binanceの技術的なポストモーテム(原因と、第2報の「ほかの侵入箇所」)、Proof of Reservesの完全な証明(11月3日予定)、凍結資産の扱い、出金再開後の状況です。

送金・決済・資産移動の設計をレビューしたい方へ

筆者は、決済プラットフォームの信頼性レイヤー(冪等性・整合性・二重課金の防止)の設計・実装を主導してきました。この記事のような視点で、貴社のバックエンド・決済API・クラウドの権限・資金移動の制御を設計レビューすることができます。

対応できること、できないことを先に書きます。

  • できること: 送金・決済のAPI、承認フロー、限度額と冪等性、クラウドのIAMとサービスの権限、監査ログと異常検知の設計レビュー。優先順位つきの改善案と、同時実行・失敗系のテストの設計
  • できないこと: 暗号資産のカストディ(保管)の専門的な監査、鍵の管理(HSM・MPCの運用)の評価、インシデントのフォレンジック調査。これらは専門の事業者にご相談ください
  • 「完全に安全になる」とはお約束できません。見つかったことと、見ていない範囲を、そのまま報告します

範囲と料金は、下のボタンの先でご確認ください。

よくある質問

Binanceの流出額は63億円ですか?
いいえ。Binanceの第2報は『approximately $6.3B USD』と書いており、約63億米ドルです。円換算は為替で変わります。調査会社の見積もりは、TRM Labsが盗まれた時点の価格で約63.6億ドル、Ellipticが約64.3億ドルで、対象チェーン数と集計の時点が違います。
Binanceの秘密鍵は漏えいしたのですか?
確定していません。Binanceは『現時点で、ウォレットの秘密鍵が漏えいした証拠は見つかっていない』と述べていますが、これは漏えいしていないという断定ではありません。Ellipticは、攻撃者がBinance自身のシステムに署名させたように見えると分析しています。技術的なポストモーテム(事後分析)は、2026年11月1日の時点で公表されていません。
凍結された約30億ドルは戻ってきたのですか?
いいえ。凍結は、TetherやCircleなどの発行体が該当アドレスのトークンを動かせなくした状態で、Binanceの手元に戻った(回収)わけではありません。回収額は公表されていません。補填の90%はBinanceが自社資金・SAFU・先物保険基金で用意したもので、これも回収とは別です。Ellipticは、ビットコイン・XRP Ledger・Solana・NEAR上で盗まれた分は凍結されていないとしています。
秘密鍵をHSMやMPCで守っていれば防げたのではないですか?
HSMやMPCが防ぐのは鍵の持ち出しで、正規の経路から届いた署名要求に応じてしまうことは防ぎません。EIP-7702の委任署名は、金額も送金先も含まない形で、アカウントの動作を別のコードに委ねられます。署名する内容を検査するポリシーの層と、職務の分離が別に必要です。ただし、今回Binanceがどの方式で鍵を守っていたかは公表されていません。
Binanceの出金は再開しましたか?
2026年11月1日1時(日本時間)に確認した時点では、再開していません。第3報(10月31日)は、11月1日(日曜)に段階的に再開する予定だとしています。入金は、10月30日の更新以降の公式発表で通常どおり稼働しているとされています。日本法人は暗号資産の出庫のみを止め、入庫・売買・日本円の入出金は通常どおりと報じられています。
自社で送金や決済の機能を持つ場合、何から確かめるべきですか?
署名サービスが、呼び出し元の申告ではなく署名する実バイト列をデコードして判定しているか。送金以外の署名(承認・委任・権限移譲)を既定で拒否しているか。承認が特定の要求に束縛され、期限を持つか。限度額の確認と更新が原子的か。本番の署名経路に、人の端末から届く経路がないか。この5点から確かめます。

参考文献

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

本番の顧客データを預かる前に

Webアプリ・SaaS のセキュリティ監査 — 認可・テナント分離・設定まで、コードを読んで確かめます

ツールが拾える穴に加えて、「誰がどのデータに触れてよいか」という設計の穴まで、ソースコードと設定から確かめ、優先順位つきの修正方針を出します。Next.js / Supabase に限らず、Rails・Laravel・Django・Go などの Web アプリと AWS / GCP / Vercel の設定も対象です。「完全に安全」とは言いません。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

あわせて読みたい