defi-attack-patterns について
スマートコントラクトやプロトコル設計を調査する分析者向けのDeFiセキュリティプレイブックです。フラッシュローン、オラクル、MEV、ガバナンス、ブリッジ、トークン規格に関する攻撃パターンを扱います。
主な機能
- 01フラッシュローン攻撃の仕組み
- 02現物価格とTWAPオラクルのリスク
- 03MEV抽出パターン
- 04精度損失とVaultインフレーション攻撃
- 05ガバナンスとブリッジの脆弱性
- 06トークン規格のエッジケース
活用シーン
- 01DeFiオラクル設計のレビュー
- 02Vaultのシェア計算の評価
- 03ガバナンス投票の保護策の分析
- 04ブリッジのメッセージ検証の監査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill defi-attack-patternsインストール後、Claude Code で/defi-attack-patternsを入力して読み込まれたか確認します。
詳細
スキル:DeFi 攻撃パターン — 専門家向け攻撃プレイブック
AI LOAD INSTRUCTION:DeFi の高度な悪用手法です。フラッシュローンの仕組み、オラクル操作(スポット価格と TWAP)、MEV の抽出(サンドイッチ、JIT、清算)、精度損失攻撃、ガバナンス攻撃、ブリッジの脆弱性、トークン標準の落とし穴を扱います。ベースモデルは、フラッシュローンにおける単一トランザクションのアトミック性制約や、スポット価格の操作と TWAP の操作の違いを見落としがちです。
0. 関連するルーティング
- smart-contract-vulnerabilities:基盤となる Solidity の脆弱性パターン(リエントランシー、整数オーバーフロー、delegatecall)
- deserialization-insecure:オフチェーンのブリッジリレイヤーやインデクサーのインフラを標的にする場合
1. フラッシュローン攻撃
1.1 仕組み
フラッシュローンでは、単一トランザクション内で無担保借入ができます。借入 → 利用 → 返済のサイクル全体をアトミックに完了させる必要があります。返済に失敗すると、何も起きなかったかのようにトランザクションがリバートされます。
| プロバイダー | 最大額 | 手数料 |
|---|---|---|
| Aave V3 | アセットごとのプール流動性 | 0.05%(承認済みの借り手は 0 にできる場合があります) |
| dYdX | プール流動性 | 0(内部残高の操作を利用) |
| Uniswap V3 | ペアごとのプール流動性 | 0.3%(スワップ手数料ティア) |
| Balancer | プール流動性 | プロトコルで設定可能 |
1.2 価格オラクルの操作
1. Flash borrow 100,000 WETH
2. Swap 100,000 WETH → TOKEN on AMM_A
→ TOKEN spot price on AMM_A skyrockets
3. On Lending_Protocol (reads AMM_A spot price as oracle):
→ Deposit small TOKEN collateral (valued at inflated price)
→ Borrow large amount of WETH against it
4. Swap TOKEN back → WETH on AMM_A (restore price)
5. Repay flash loan (100,000 WETH + fee)
6. Keep borrowed WETH from Lending_Protocol minus collateral cost
重要なポイント:AMM のスポット準備金(getReserves())を価格オラクルとして使うプロトコルは脆弱です。TWAP または外部オラクル(Chainlink)を使う必要があります。
1.3 リエントランシーによる流動性プールの流出
フラッシュ借入 → プールに入金 → コールバック中にリエントランシーを発生させる → 入金額を超えて出金 → ローンを返済します。
フラッシュローンの資金力と、プールの会計ロジックにおけるリエントランシーを組み合わせて悪用します。
1.4 ガバナンスへのフラッシュ借入
1. Flash borrow governance tokens
2. Create/vote on malicious proposal (if no snapshot or timelock)
3. Proposal passes instantly
4. Execute proposal (drain treasury, change admin, etc.)
5. Return governance tokens
防御策:スナップショット方式の投票(Compound Governor Bravo)、タイムロック、提案の最短期間。
2. 価格オラクルの操作
2.1 スポット価格と TWAP
| オラクルの種類 | 操作コスト | 時間枠 |
|---|---|---|
スポット価格(getReserves()) | 1 回の大規模スワップ(フラッシュローンで調達可能) | 同一トランザクション内 |
| TWAP(時間加重平均) | 複数ブロックにわたる継続的な操作 | 複数ブロック(高コスト) |
| Chainlink アグリゲーター | オラクルノードの過半数以上を侵害 | 実質的に不可能 |
2.2 AMM 操作の流れ
Normal state: Pool has 1000 ETH + 1,000,000 USDC → price = 1000 USDC/ETH
Attack:
├── Swap 9000 ETH into pool
│ Pool now: 10000 ETH + 100,000 USDC (constant product)
│ Spot price: 10 USDC/ETH (crashed 100x)
├── Dependent contract reads this price
│ → Liquidates positions at wrong price
│ → Or allows cheap borrowing against ETH collateral
├── Swap back: buy ETH with USDC
│ Price restores to ~1000 USDC/ETH
└── Net profit = value extracted from dependent contract - swap slippage - fees
2.3 Chainlink オラクルの陳腐化
(, int price, , uint updatedAt, ) = priceFeed.latestRoundData();
// Missing checks:
// 1. price > 0
// 2. updatedAt != 0
// 3. block.timestamp - updatedAt < HEARTBEAT
// 4. answeredInRound >= roundId
オラクルが古い場合(ネットワークの混雑、L2 シーケンサーの停止)、価格が何時間も前のものになることがあり、古い価格を利用した裁定取引が可能になります。
L2 シーケンサーのリスク:Arbitrum/Optimism のシーケンサーが停止すると、Chainlink の価格が凍結します。復旧時に価格が急変し、誤った価格で大量の清算が発生する可能性があります。
3. MEV(最大抽出可能価値)
3.1 サンドイッチ攻撃
Mempool observation: victim submits swap TOKEN_A → TOKEN_B with slippage 1%
Front-run: Buy TOKEN_B (increase price)
Victim tx: Swap executes at worse price (within slippage tolerance)
Back-run: Sell TOKEN_B (profit from price impact)
Profit = victim's price impact - gas costs × 2
3.2 JIT(ジャストインタイム)流動性
1. Observe large pending swap in mempool
2. Provide concentrated liquidity in the exact price range (Uniswap V3 tick)
3. Victim's swap executes → JIT LP earns majority of fees
4. Remove liquidity immediately after swap
5. Profit = fee earned - gas - impermanent loss (minimal for single block)
3.3 清算 MEV
1. Monitor lending protocols for positions approaching liquidation threshold
2. When price oracle updates → position becomes liquidatable
3. Front-run other liquidators → execute liquidation
4. Receive liquidation bonus (typically 5-15% of collateral)
5. Sell collateral for profit
3.4 MEV 保護メカニズム
| メカニズム | 仕組み |
|---|---|
| Flashbots Protect | トランザクションをプライベートメンプールに送信し、ブロックビルダーだけが閲覧できます |
| MEV Blocker | MEV 対応リレイヤーを経由する RPC エンドポイントです |
| Cow Protocol(バッチオークション) | バッチマッチングにより、トランザクション順序による優位性を排除します |
| 暗号化メンプール | 閾値暗号化を使用し、ブロック構築時にのみ復号します |
| MEV-Share | ユーザーは、自分のトランザクションから抽出された MEV の一部を受け取ります |
4. 精度損失の悪用
4.1 トークン計算における丸め誤差
Solidity には浮動小数点数がありません。整数除算では端数が切り捨てられます。
shares = depositAmount * totalShares / totalAssets
totalAssets が depositAmount * totalShares に対して非常に大きい場合、結果が 0 に丸められ、預金者がシェアを受け取れない一方で、プールには預け入れた資産が残ります。
4.2 初回預金者/ボールトのインフレーション攻撃
1. Attacker deposits 1 wei → receives 1 share
2. Attacker donates 1,000,000 tokens directly to vault (not via deposit)
3. Vault state: 1,000,001 tokens, 1 share
4. Victim deposits 999,999 tokens:
shares = 999,999 * 1 / 1,000,001 = 0 (integer truncation)
5. Victim gets 0 shares; attacker owns 100% of vault (now 2,000,000 tokens)
6. Attacker withdraws all
防御策:
- 初回預け入れ時にデッドシェアを発行する(OpenZeppelin ERC4626 オフセット)
- 初期預け入れ額に最小値を設定する
- 仮想オフセットを使って内部会計を行う
4.3 精度切り捨てによるダスト攻撃
切り捨てのたびに 1 wei が失われる小さな操作を繰り返します。数千回にわたって蓄積すると、無視できない損失になります。
5. ガバナンス攻撃
5.1 フラッシュローンによるガバナンス攻撃
ガバナンストークンを借りて投票し、返却します。この攻撃が可能なのは、投票前にプロトコルが残高をスナップショットしない場合に限られます。
5.2 タイムロックの回避
| ベクトル | 手法 |
|---|---|
| タイムロックを 0 に設定 | 管理者が提案を即座に実行できます |
emergencyExecute 関数 | 「緊急時」にタイムロックを回避します |
| ガーディアン/マルチシグによる上書き | 単一障害点になります |
| 攻撃者による提案のキャンセル | しきい値に達していれば、キャンセルをフロントランします |
5.3 定足数の操作
Protocol requires 10% quorum (10M tokens out of 100M supply)
├── Flash borrow 10M governance tokens
├── Create proposal: set admin = attacker
├── Vote with borrowed tokens → meets quorum
├── If no timelock: execute immediately
└── Return tokens
6. ブリッジのエクスプロイト
6.1 代表的なブリッジ攻撃ベクトル
| ベクトル | 例 |
|---|---|
| 署名検証の回避 | Ronin Bridge(6 億 2,400 万ドル)— 9 人中 5 人のバリデーターが侵害されました |
| メッセージのリプレイ | 複数のチェーンでデポジット証明をリプレイします |
| 偽のデポジット証明 | 存在しない L1 デポジットの証明を送信します |
| バリデーターの共謀 | ブリッジのバリデーターの過半数が侵害されます |
| スマートコントラクトのバグ | Wormhole(3 億 2,000 万ドル)— ガーディアンセットが初期化されていませんでした |
| アップグレード可能なプロキシのエクスプロイト | 攻撃者がアップグレード権限を取得し、実装を差し替えます |
6.2 クロスチェーンメッセージの検証
Secure pattern:
├── Source chain: emit event with (destination, amount, nonce, chainId)
├── Relayer: submit proof (Merkle proof of event inclusion)
├── Destination chain: verify proof against known source block header
│ ├── Check nonce not replayed
│ ├── Check chainId matches
│ ├── Verify Merkle proof against trusted root
│ └── Mint/release tokens
Vulnerable pattern:
├── Relayer: submit (destination, amount) signed by N-of-M validators
└── If M is small or keys are compromised → forge signatures
7. トークン規格の特殊ケース
7.1 ERC-20 の承認を狙ったフロントランニング
1. Alice approves Bob for 100 tokens
2. Alice wants to change approval to 50 tokens
3. Bob sees the approval change tx in mempool
4. Bob front-runs: transferFrom(Alice, Bob, 100) — uses old approval
5. Alice's approval change executes: approval = 50
6. Bob calls transferFrom(Alice, Bob, 50) — uses new approval
7. Bob extracted 150 tokens instead of 50
防御策:まず approve(0) を実行し、次に approve(newAmount) を実行します。または increaseAllowance/decreaseAllowance を使用します。
7.2 フックを介した ERC-777 のリエントランシー
ERC-777 トークンは、転送を完了する前に受取人の tokensReceived() フックを呼び出します。これは典型的なリエントランシー攻撃のベクトルです。
transfer(attacker, amount)
├── _beforeTokenTransfer hook
├── Balance update
├── tokensReceived() callback to recipient ← reentrancy window
│ └── attacker re-enters: transfer, swap, deposit, etc.
└── _afterTokenTransfer hook
7.3 転送時に手数料が差し引かれるトークン
転送のたびに手数料が差し引かれるトークンです。プロトコルが受け取る額は amount を下回ります。
// Vulnerable: assumes received == amount
token.transferFrom(msg.sender, address(this), amount);
deposits[msg.sender] += amount; // overcredits by fee amount
// Fixed: measure actual balance change
uint before = token.balanceOf(address(this));
token.transferFrom(msg.sender, address(this), amount);
uint received = token.balanceOf(address(this)) - before;
deposits[msg.sender] += received;
7.4 リベーストークン
残高が自動的に調整されるトークンです(例:Aave の aToken、stETH)。リベーストークンを保有するプロトコルでは、残高をキャッシュすると会計上の不整合が生じることがあります。
8. 主な DeFi エクスプロイトの参考資料
| エクスプロイト | 日付 | 損失額 | 主なベクトル |
|---|---|---|---|
| Ronin Bridge | 2022 年 3 月 | 6 億 2,400 万ドル | バリデーターキーの侵害 |
| Wormhole | 2022 年 2 月 | 3 億 2,000 万ドル | 署名検証のバグ |
| Beanstalk | 2022 年 4 月 | 1 億 8,200 万ドル | フラッシュローンによるガバナンス攻撃 |
| Mango Markets | 2022 年 10 月 | 1 億 1,400 万ドル | オラクル操作 |
| Euler Finance | 2023 年 3 月 | 1 億 9,700 万ドル | 寄付攻撃+清算ロジック |
| Curve(リエントランシー) | 2023 年 7 月 | 7,300 万ドル | Vyper コンパイラーのリエントランシーバグ |
9. 判断ツリー
Analyzing a DeFi protocol?
├── Does it use price oracles?
│ ├── Spot price (AMM reserves)? → Flash loan manipulation (Section 1.2)
│ │ └── Can oracle be manipulated in single tx? → HIGH RISK
│ ├── TWAP? → Multi-block manipulation needed → MEDIUM RISK
│ ├── Chainlink? → Check staleness handling (Section 2.3)
│ │ ├── Heartbeat check present? → OK
│ │ └── L2? → Check sequencer uptime oracle
│ └── Multiple oracles with fallback? → Evaluate each
├── Does it accept external tokens?
│ ├── Yes → Check fee-on-transfer handling (Section 7.3)
│ ├── ERC-777 tokens accepted? → Reentrancy via hooks (Section 7.2)
│ └── Rebasing tokens? → Accounting mismatch (Section 7.4)
├── Does it have governance?
│ ├── Yes → Flash loan governance possible? (Section 5.1)
│ │ ├── Snapshot-based voting? → Safer
│ │ └── Live balance voting? → Flash borrow attack
│ ├── Timelock present? → Check for bypass (Section 5.2)
│ └── Quorum threshold vs flash-loanable supply? (Section 5.3)
├── Is it a vault / yield aggregator?
│ ├── Yes → First depositor attack (Section 4.2)
│ │ └── Virtual offset or dead shares? → Mitigated
│ └── Precision loss in share calculation? (Section 4.1)
├── Is it a bridge?
│ ├── Yes → Load bridge vectors (Section 6)
│ │ ├── Validator set size and key management?
│ │ ├── Replay protection (nonce + chainId)?
│ │ └── Upgradeable? → Who holds upgrade key?
│ └── No → Continue
├── User-facing swap functionality?
│ ├── Yes → MEV exposure (Section 3)
│ │ ├── Slippage protection enforced?
│ │ └── Private mempool integration?
│ └── No → Continue
└── Load [smart-contract-vulnerabilities](../smart-contract-vulnerabilities/SKILL.md)
for underlying Solidity-level bugs