Appearance
CTF: Selfie チャレンジ ― DVT 資金を奪取する技術
「これは新しい貸付プールだ!DVT トークンのフラッシュローンを提供している。さらに、おしゃれなガバナンス機能まである。一体何が問題になるんだろう?…(心の声略)」
DeFi プロジェクトにフラッシュローンとガバナンス機能が組み合わさると、何が起こるでしょうか? Damn Vulnerable DeFi の Selfie チャレンジは、この興味深く(そして危険でもある)シナリオを深く理解するための絶好の機会です。
チャレンジ目標
あなたの任務は:
- プール内の すべての DVT トークンを回収
- 指定された recovery アカウントへ送金
しかし注意:
- 初期状態では DVT を1枚も持っていない
- プールには 150万 DVT が存在
脆弱性の根源
■ SelfiePool
- フラッシュローン機能を提供
- 手数料 0
- 任意の量の DVT を一時的に借りられる
ただし:
emergencyExitはonlyGovernanceにより制限
■ SimpleGovernance
- 提案と実行が可能なガバナンス機構
queueAction実行には:
👉 総供給量の過半数以上の投票権が必要
通常は:
- 大量の
DamnValuableVotesトークン保有が必要
攻撃戦略
1. フラッシュローンで DVT を取得
- プールから 全 DVT を借入
- 一時的に巨大な残高を持つ
2. コールバック内で操作
onFlashLoan 内で:
■ 投票権の確保
delegateを実行- 自分に投票権を集中
■ 悪意ある提案
solidity
abi.encodeWithSignature("emergencyExit(address)", recovery);
- プールから資金を引き出す提案を作成
■ 提案登録
solidity
governance.queueAction(...)
👉 過半数の投票権を一時的に満たしているため成功
■ フラッシュローン返済準備
approveにより返済可能にする
3. 時間経過を待つ
- ガバナンスには 遅延(約2日) がある
4. 提案の実行
solidity
governance.executeAction(actionId);
5. 結果
👉 SelfiePool の全 DVT が:
👉 recovery アドレスへ送金
コード構成(MyContract)
■ exploit
solidity
pool.flashLoan(...)
■ onFlashLoan
solidity
token.delegate(address(this));
actionId = governance.queueAction(...);
token.approve(address(pool), amount);
■ execute
solidity
governance.executeAction(actionId);
このチャレンジの本質
🔹 フラッシュローンの悪用
- 一時的な資産でも影響力を持てる
🔹 ガバナンスの欠陥
- 「スナップショットなし」の投票設計
- 一瞬の残高で支配可能
🔹 時間遅延の利用
- 即時ではなく「遅延実行」
- 攻撃者に準備時間を与える
まとめ
Selfie チャレンジは以下を融合しています:
- フラッシュローン
- ガバナンス
- 投票権委任
- 時間遅延
そして示しているのは:
👉 「一時的な資産でも、ガバナンスを乗っ取れる」
DeFi において重要なのは:
「誰がどれだけ持っているか」ではなく、 「いつ持っているか」
準備はいいですか? 次に資金を“救う”のはあなたです。