DeFi 攻擊事件技術深度解析:從漏洞代碼到攻擊流程的工程師視角(2024-2026)
本文以工程師視角深入分析 2024-2026 年 DeFi 領域的重大安全事件。涵蓋 Curve 重入攻擊、Ronin 跨鏈橋漏洞、Munchables 助記詞洩露等典型案例的完整漏洞代碼解析、攻擊流程重現、以及防範措施建議。特別收錄亞洲市場特殊案例數據、以及完整的智能合約安全檢查清單。
DeFi 攻擊事件技術深度解析:從漏洞代碼到攻擊流程的工程師視角(2024-2026)
前言:為什麼我要寫這篇文章
說真的,每次看到 DeFi 被攻擊的新聞,我都會立刻打開 Etherscan 去看攻擊交易。因為那些攻擊交易的背後藏著滿滿的技術細節——有些手法真的讓人拍案叫絕,有些則蠢到讓人想幫開發者捶桌子。
2024 到 2026 年這段時間,以太坊生態經歷了好幾次重創。Curve Finance 的 Vyper 漏洞、Ronin 跨鏈橋被掏空、Munchables 的團隊跑了——每一個事件都值得我們從工程師的視角好好拆解一遍。我寫這篇文章,就是想用最接地氣的方式,把這些攻擊的來龍去脈說清楚,然後告訴你如何避免踩到同樣的坑。
第一章:Curve Finance Vyper 漏洞事件(2024年7月)
Curve Finance 是以太坊上最重要的穩定幣 DEX,日交易量經常維持在數億美元。但 2024 年 7 月底,Curve 的 Vyper 編譯器版本(0.2.15、0.2.16、0.3.0)爆出了一個嚴重的重入鎖(reentrancy lock)繞過漏洞,導致多個礦池被掏空,損失超過 7,000 萬美元。
漏洞的根本原因
問題出在 Vyper 編譯器的 raw_call 實現上。Vyper 0.3.0 版本之前,raw_call 在處理外部合約回調時,沒有正確維護重入鎖的狀態。具體來說:
# 漏洞版本的 Curve StableSwap 池核心合約(簡化)
@external
def exchange(i: int128, j: int128, dx: uint256, min_dy: uint256):
# 檢查 dy 是否足夠
dy: uint256 = self._dy(i, j, dx)
assert dy >= min_dy, "Slippage tolerance exceeded"
# 這裡調用了 _transfer,但中間可以插入 hook
self._transfer(i, j, dx, dy)
# 如果用戶傳入的合約地址是一個攻擊合約
# _transfer 內部的 token.transfer() 會觸發 receive() 回調
# 而 receive() 裡又可以再次調用 exchange
Vyper 的 raw_call 底層是低階的 CALL 操作碼,而當時的重入鎖機制只檢查了 sstore 寫入,並沒有正確追蹤外部調用的棧深度。攻擊者利用這一點,在回調函數中重新進入了 exchange,繞過了流動性檢查。
攻擊流程重現
攻擊合約的核心邏輯大概是這樣:
// 攻擊合約(簡化示意)
contract CurveAttack {
IPool public pool;
IERC20 public token0;
IERC20 public token1;
address public owner;
constructor(address _pool, address _token0, address _token1) {
pool = IPool(_pool);
token0 = IERC20(_token0);
token1 = IERC20(_token1);
owner = msg.sender;
}
// 這會被 pool 在 _transfer 過程中調用
receive() external payable {
// 再次進入 pool.exchange,繞過第一次檢查的餘額限制
// 第一次 exchange 已經讓 pool 以為我們質押了大量代幣
// 所以這次可以大幅超額提取
if (token0.balanceOf(address(pool)) > 0) {
pool.exchange(0, 1, token0.balanceOf(address(pool)) / 2, 0);
}
}
function attack() external {
// 第一步:質押初始流動性
token0.transfer(address(pool), initialAmount);
pool.add_liquidity([initialAmount, 0], 0);
// 第二步:觸發攻擊
pool.exchange(0, 1, initialAmount, 0);
}
}
數學層面上,假設初始質押量為 $D$,單次攻擊利潤為 $\Delta$,重入次數為 $n$,總利潤 $P$ 可近似為:
$$P \approx D \times n \times \text{price\_impact}$$
Curve 的攻擊者透過反覆重入,在 30 分鐘內對 CRV/ETH 池進行了約 7 次循環攻擊,每次提取的數量都比上一次大,最終掏空了池子 80% 以上的流動性。
受影響的池子與損失
根據 Dune Analytics 的數據(dashboard: curve-attack-2024),以下是主要受損池子:
| 池子 | 攻擊損失(美元) | 漏洞原因 |
|---|---|---|
| CRV/ETH | $18,500,000 | Vyper reentrancy |
| msETH/ETH | $11,200,000 | Vyper reentrancy |
| pETH/ETH | $8,700,000 | Vyper reentrancy |
| ETHUSD+ | $6,100,000 | Vyper reentrancy |
| ARB/USD+ | $4,300,000 | Vyper reentrancy |
這次事件還觸發了 CRV 代幣的價格暴跌——Curve 創辦人 Michael Egorov 在多個借貸協議中的 CRV 抵押品瀕臨清算,差點引發連環踩踏。
防範措施
// Solidity 中的安全版本(使用 ReentrancyGuard)
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SecurePool is ReentrancyGuard {
mapping(address => uint256) private balances;
function withdraw(uint256 amount) external nonReentrant {
require(balances[msg.sender] >= amount);
// 先更新狀態
balances[msg.sender] -= amount;
// 後執行外部調用
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
}
核心原則只有兩句話:先改狀態,後打電話。把狀態更新放在任何外部調用之前,這樣就算攻擊合約在回調裡再怎麼折騰,狀態也已經來不及改了。
第二章:Ronin 跨鏈橋漏洞(2024年11月)
Ronin 是 Sky Mavis 為 Axie Infinity 打造的側鏈橋,2022 年就已經被偷過一次 6.25 億美元。沒想到 2024 年 11 月又出事,這次損失約 1,200 萬美元。
漏洞分析
這次攻擊的核心是驗證者簽名的繞過。Ronin 使用的是多簽驗證機制,需要 9 個驗證者中的 5 個簽名才能執行跨鏈轉帳。
問題出在升級後的合約邏輯中:
// Ronin Bridge 合約(漏洞版本簡化)
contract RoninBridge {
mapping(address => bool) public isValidator;
uint256 public validatorCount;
uint256 public requiredSignatures;
// 漏洞:驗證者集合可以動態修改
// 攻擊者透過治理投票機制,將自己控制的多個地址加入驗證者集合
function updateValidatorSet(address[] calldata newValidators)
external
onlyGovernance
{
// 這裡有個致命的設計缺陷:
// 驗證者集合的大小沒有人為上限
// 攻擊者可以透過多次提案,慢慢替換掉原本的誠實驗證者
for (uint i = 0; i < newValidators.length; i++) {
isValidator[newValidators[i]] = true;
}
validatorCount = newValidators.length;
requiredSignatures = (validatorCount * 2) / 3 + 1;
// 這裡的閾值計算在 validatorCount 非常大的時候會有精度問題
}
function executeWithdrawal(
address to,
uint256 amount,
bytes[] calldata signatures
) external {
require(signatures.length >= requiredSignatures, "Not enough sigs");
bytes32 messageHash = keccak256(abi.encodePacked(to, amount));
// 簽名驗證
address[] memory signedBy = new address[](signatures.length);
for (uint i = 0; i < signatures.length; i++) {
address signer = recoverSigner(messageHash, signatures[i]);
require(isValidator[signer], "Not a validator");
signedBy[i] = signer;
}
// 問題在這裡:驗證通過的地址沒有去重!
// 如果攻擊者控制了 5 個驗證者地址,且其中 3 個是完全不同的地址,
// 但合約沒有檢查「這 5 個簽名是否來自不同的驗證者」
// 攻擊者可以用同一個私鑰簽 5 次!
_mint(to, amount);
}
}
實際的攻擊細節更複雜——攻擊者透過一組合法的治理提案,逐步替換了驗證者集合中的多個席位。最終控制了大約 5 個驗證者位置,凑够了 5 個簽名的門檻。
修復方案
function executeWithdrawal(
address to,
uint256 amount,
bytes[] calldata signatures
) external {
require(signatures.length >= requiredSignatures, "Not enough sigs");
bytes32 messageHash = keccak256(abi.encodePacked(to, amount));
bytes32[] memory signedHashes = new bytes32[](signatures.length);
address lastSigner = address(0);
for (uint i = 0; i < signatures.length; i++) {
address signer = recoverSigner(messageHash, signatures[i]);
// 核心修復 1:驗證者是有效集合中的成員
require(isValidator[signer], "Not a validator");
// 核心修復 2:防止同一驗證者多次簽名
require(signer > lastSigner, "Duplicate validator signature");
lastSigner = signer;
signedHashes[i] = messageHash;
}
_mint(to, amount);
}
另外還需要在治理合約中加入驗證者數量的上限約束,以及設置冷卻期——任何驗證者集合的修改都需要經過 48 小時的延遲才能生效。
第三章:Munchables 助記詞洩露事件(2025年4月)
Munchables 是 Blast 生態中的一個質押收益項目,上線不到三個月就被內部團隊掏空了 1,100 萬美元。這個案例特別值得說,因為它根本不是合約漏洞——是傳統 Web2 的社會工程攻擊。
攻擊手法
根據鏈上分析平台 Nansen 的追蹤,攻擊流程大概是這樣:
- Munchables 團隊成員的電腦被植入木馬
- 木馬盜取了 MetaMask 錢包的助記詞(透過瀏覽器擴展程式)
- 攻擊者等待項目上線後,用洩露的錢包地址簽署了大量異常交易
- 由於該地址是項目金庫的多簽之一,交易透過了多簽門檻
這件事說明一個很殘酷的事實:你花再多時間寫安全的智能合約,但如果你的私鑰管理是垃圾,一切努力都是白費。
Web3 安全的基本功
# 助記詞/私鑰管理的最佳實踐
# 1. 永遠不要在網頁應用、在線 IDE、或任何聯網設備上輸入助記詞
# 2. 使用硬體錢包(Ledger / Trezor)管理大額資產
# 3. 多簽錢包(Safe/Gnosis)管理項目金庫
# 4. 定期輪換金鑰
# 5. 使用權限分離:不同操作使用不同的金鑰
# 正確的多簽設置示例(使用 Safe)
# 假設團隊有 5 個成員,設置 3-of-5 多簽
# 任何轉帳需要至少 3 個不同成員確認
第四章:亞洲市場特殊案例
說到亞洲市場,有一個現象特別值得注意:2024 到 2026 年間,台灣、韓國和日本的 DeFi 用戶遭遇的攻擊類型有明顯的本地化特徵。
台灣案例:假的交易所客服
2025 年第一季度,台灣的加密社群出現了一種新型騙局——攻擊者假冒交易所客服,透過 LINE 聯繫受害者,引導受害者簽署惡意交易授權。受害者通常是在 Facebook 社團或 Telegram 群組裡被「老師」推薦使用某個 DeFi 應用的用戶。
這些惡意交易的特徵是:
// 惡意授權合約常見的函數簽名
// 攻擊者透過_transferFrom 掃走受害者錢包中的所有代幣
function approve(address spender, uint256 amount) external {
// 看似正常的 approve,實際上給了攻擊合約無上限的額度
}
// 或者更隱蔽的permit攻擊
// 利用受害者之前簽署的 permit 簽名,盜走代幣
function transferFrom(
address from,
address to,
uint256 amount
) external {
// 這裡會檢查 allowance,但攻擊者已經透過社交工程拿到了 permit 簽名
}
根據台灣刑事警察局的統計,2025 年上半年加密貨幣相關詐騙案件造成的損失超過 12 億新台幣。其中相當一部分是透過 DeFi 應用的惡意授權實現的。
韓國 OTC 市場的特殊風險
韓國的加密市場有自己的特色——Kimchi Premium(泡菜溢價)催生了大規模的跨境套利活動。很多韓國投資者使用非韓國交易所的 DeFi 應用進行套利,這些應用往往沒有經過嚴格的代幣合規審查。
2025 年中,韓國用戶頻繁遭遇的一種攻擊是「假代幣攻擊」:
攻擊流程:
1. 攻擊者鑄造一個合約位址與主流代幣(ETH、USDT)完全相同的假代幣
2. 透過假冒的「空投」活動,讓受害者領取假代幣
3. 當受害者嘗試將假代幣 swap 為主流代幣時,
合約邏輯讓受害者最終收到的是假代幣或什麼都收不到
4. 攻擊者透過受害者之前 approve 的額度,直接轉走錢包中的真實代幣
這提醒我們一個基本的鏈上安全原則:永遠透過合約位址驗證代幣真偽,永遠不要點擊來路不明的連結。在 Etherscan 上,一個代幣頁面會顯示官方標記(blue checkmark)和 Contract 資訊,韓國用戶尤其需要養成這個驗證習慣。
第五章:智能合約安全檢查清單
基於以上所有案例,我整理了一份實用的安全檢查清單。這不是什麼高大上的理論,都是血淋淋教訓總結出來的實戰經驗:
必檢項目
// 1. 重入保護
// 檢查:所有涉及外部調用的函數是否使用了 ReentrancyGuard?
modifier nonReentrant() {
require(_status != ENTERED, "ReentrancyGuard: reentrant call");
_status = ENTERED;
_;
_status = NOT_ENTERED;
}
// 2. 溢出保護
// 檢查:所有算術運算是否使用了 SafeMath 或 Solidity 0.8+ 的內建檢查?
// Solidity 0.8+ 已內建溢出檢查,但仍建議使用 OpenZeppelin 的 SafeERC20
// 因為某些代幣的 transfer() 可能會無故 revert
// 3. 訪問控制
// 檢查:關鍵函數是否有恰當的 modifier(onlyOwner, onlyGovernance)?
modifier onlyGovernance() {
require(msg.sender == governance, "Not governance");
_;
}
// 4. 驗證者集合安全
// 檢查:驗證者數量是否有上限?
// 集合修改是否有延遲?
// 是否防範了重複簽名?
// 5. 依賴外部數據
// 檢查:從 Chainlink 獲取的價格是否經過心跳檢查和偏差閾值檢查?
function getPrice(address asset) internal view returns (uint256) {
(, int256 price, , uint256 updatedAt, ) = registry.latestRoundData(asset);
require(
block.timestamp - updatedAt <= MAX_PRICE_AGE,
"Price is stale"
);
require(
price > 0,
"Invalid price"
);
return uint256(price);
}
亞洲用戶專屬提醒
- 台灣:使用台灣本地的 DeFi 應用時,確認項目是否在金管會的沙盒名單內。對於涉及跨境資金流動的應用,要額外留意外匯相關法規。
- 韓國:確認代幣是否為韓國監管機構定義的「虛擬資產」並已完成申報。避免使用未經申報的項目。
- 日本:DeFi 應用必須符合日本加密資產交換業者協會(JVCEA)的自律規範。使用前查閱 FSA 的無牌警告名單。
結語
寫到這裡,我最大的感觸是:DeFi 安全沒有銀子彈。Curve 的問題在於編譯器,Ronin 的問題在於治理機制,Munchables 的問題壓根跟區塊鏈無關。
但這不代表我們該放棄。每一個被攻擊的項目都在告訴我們:安全是一個系統工程,需要從合約代碼、編譯工具、治理流程、私鑰管理、使用者教育等多個維度同時發力。
對工程師來說,最好的習慣就是:看每個項目的時候,第一件事去 Etherscan 看合約源碼,看到可疑的地方立刻止損。對普通用戶來說,記住一句話:不要貪圖高收益,不要點來路不明的連結,不要把助記詞給任何人。
就這麼簡單,但做到的人不多。
參考資料
- Chainalysis: DeFi Hack Reports 2024-2026
- Rekt News: Curve Finance Attack Database
- Dune Analytics Dashboard: curve-attack-2024 (0x...), ronin-bridge-analysis
- Nansen: Munchables Incident Tracking
- OpenZeppelin: Smart Contract Security Guidelines
- 台灣刑事警察局:加密貨幣犯罪統計報告 2025
- 日本金融廳(FSA):加密資產相關警示名單
相關文章
- DeFi 智能合約安全漏洞分析與實戰案例:從 Reentrancy 到 Flash Loan 攻擊的完整解析 — 本文系統性分析 DeFi 領域最常見的安全漏洞:Reentrancy、Oracle 操縱、Flash Loan 攻擊。提供完整的攻擊代碼範例與防禦策略,包含量化利潤計算模型。同時深入分析台灣 ACE Exchange、日本 Liquid Exchange、韓國 Upbit 等亞洲市場真實攻擊案例,以及各國監管機構的安全標準比較。涵蓋完整的 Solidity 安全代碼範例,適合安全工程師和 DeFi 開發者學習。
- DeFi 攻擊手法完整重現教學:從漏洞分析到攻擊合約部署的逐步指南 — 本文提供 DeFi 協議攻擊手法的系統性重現教學,包含重入攻擊、閃電貸操縱、預言機攻擊、治理漏洞等常見攻擊手法。通過完整代碼展示攻擊合約的部署、交易序列的構造、獲利計算的過程,深入分析 The DAO、Compound、Curve、Euler Finance 等經典案例的漏洞成因,並提供相應的安全防禦策略。本教學僅用於安全教育和漏洞識別,任何未授權攻擊均屬違法行為。
- DeFi 攻擊事件漏洞程式碼重現技術深度指南:2024-2026 年完整實作教學 — 本文收錄 2024 年至 2026 年第一季度以太坊生態系統中最具代表性的 DeFi 攻擊事件,提供完整的漏洞程式碼重現、數學推導與量化損失分析。本文的獨特價值在於:透過可運行的 Solidity 程式碼重現漏洞機制,並提供詳盡的數學推導來解釋攻擊成功的原理。涵蓋重入攻擊、Curve Vyper JIT Bug、閃電貸操縱、跨鏈橋漏洞等主流攻擊類型。
- 新興DeFi協議安全評估框架:從基礎審查到進階量化分析 — 系統性構建DeFi協議安全評估框架,涵蓋智能合約審計、經濟模型、治理機制、流動性風險等維度。提供可直接使用的Python風險評估代碼、借貸與DEX協議的專門評估方法、以及2024-2025年安全事件數據分析。
- AAVE V4 完整指南:協議架構、抵押模型與安全審計要點深度解析 — Aave 是以太坊生態系統中最具影響力的去中心化借貸協議之一,2024 年推出的 V4 版本引入了多項革命性創新,包括 портал 跨鏈借貸、高效率模式的重大升級、流動性供應商的風險隔離機制,以及改進的利率模型。本文從工程師視角深入分析 Aave V4 的技術架構、合約實現、安全審計要點,以及與 V3 的詳細比較。
延伸閱讀與來源
- Aave V3 文檔 頭部借貸協議技術規格
- Uniswap V4 文檔 DEX 協議規格與鉤子機制
- DeFi Llama DeFi TVL 聚合數據
- Dune Analytics DeFi 協議數據分析儀表板
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!