背景介紹
2024 年 7 月 12 日,DoughFina 協議遭受了駭客攻擊,造成本次攻擊的主要原因是 ConnectorDeleverageParaswap
合約沒有對輸入引數進行檢查,且該合約為 DSA
合約的 owner
。攻擊者可以構造惡意引數竊取 DSA
合約的資金。
攻擊交易
https://app.blocksec.com/explorer/tx/eth/0x92cdcc732eebf47200ea56123716e337f6ef7d5ad714a2295794fdc6031ebb2e
相關合約
- DSA(被攻擊地址):0x534a
在 AAVE V3 上質押了 596 WETH,借出了 938566 USDC - 攻擊合約:0x11a8
- ConnectorDeleverageParaswap:0x9f54e8eaa9658316bb8006e03fff1cb191aafbe6
透過閃電貸協助 DSA 降低在 AAVE V3 上的槓桿。
攻擊交易分析
這個章節我們先嚐試從 trace 來定位漏洞的位置。
透過對這筆交易進行一個大概的觀察,如下圖所示,攻擊者在發起攻擊之前,先利用閃電貸的資金幫 0x534a 歸還了他的借款 938566 USDC,其他部分都是常規的操作,其中需要深入調查的就是 0x11a8
呼叫 ConnectorDeleverageParaswap.flashloanReq
函式的過程。
ConnectorDeleverageParaswap.flashloanReq
函式
我們看到在 ConnectorDeleverageParaswap.flashloanReq
函式中,會呼叫 POOL.flashLoan
POOL.flashLoan
執行一個常規的閃電貸流程
- ConnectorDeleverageParaswap 合約從閃電貸獲取 5 USDC
- 呼叫 ConnectorDeleverageParaswap.executeOperation 函式
- 歸還 5.025 USDC
- handleRepayment
繼續跟進到 ConnectorDeleverageParaswap.executeOperation
函式,可以看到它對傳入的引數進行解析後直接呼叫 deloopInOneOrMultipleTransactions
函式
對 deloopInOneOrMultipleTransactions
函式進行分析
function deloopInOneOrMultipleTransactions(bool opt, address _dsaAddress, address[] memory assets, uint256[] memory amounts, uint256[] memory premiums, address[] memory collateralTokens, uint256[] memory collateralAmounts, bytes[] memory multiTokenSwapData) private {
// Repay all flashloan assets or withdraw all collaterals
// 使用閃電貸獲得的資金來償還使用者在 Aave 上的債務。
repayAllDebtAssetsWithFlashLoan(opt, _dsaAddress, assets, amounts);
// Extract all collaterals
// 從使用者的 DSA 中提取指定數量的抵押品。
extractAllCollaterals(_dsaAddress, collateralTokens, collateralAmounts);
// Deloop all collaterals
// 使用 Paraswap 將提取的抵押品換成債務代幣
deloopAllCollaterals(multiTokenSwapData);
// Repay all flashloan assets or withdraw all collaterals
// 償還閃電貸,然後將剩餘的資金存回 Aave 或轉移到金庫
repayFlashloansAndTransferToTreasury(opt, _dsaAddress, assets, amounts, premiums);
}
不過在檢視 ConnectorDeleverageParaswap.executeOperation 函式的執行 trace 時,發現 Phalcon 把呼叫的四個函式混在一起了不好分辨。
根據轉移的金額確定攻擊發生的位置,猜測這筆 WETH
的轉賬與漏洞的利用有關。
所以透過單步除錯的方式來檢查發生了什麼。
執行到 ConnectorDeleverageParaswap.deloopAllCollaterals
函式中時,對傳入的 multiTokenSwapData
引數進行解析,得到對應的引數: flashloanVars.srcToken, flashloanVars.destToken, flashloanVars.srcAmount, flashloanVars.destAmount, flashloanVars.paraSwapContract, flashloanVars.tokenTransferProxy, flashloanVars.paraswapCallData
其中 paraSwapContract
(out4)對應的地址為 WETH 的合約地址(0xc02a),而不是進行 swap 的合約地址。
當執行到 paraSwapContract.call
部分的函式時,由於 paraSwapContract
的地址已被替換為 WETH9
的地址,且 paraswapCallData
為攻擊者構造的轉賬 calldata,所以實際執行的是 WETH
的轉賬操作
function deloopAllCollaterals(bytes[] memory multiTokenSwapData) private {
FlashloanVars memory flashloanVars;
for (uint i = 0; i < multiTokenSwapData.length;) {
// Deloop
(flashloanVars.srcToken, flashloanVars.destToken, flashloanVars.srcAmount, flashloanVars.destAmount, flashloanVars.paraSwapContract, flashloanVars.tokenTransferProxy, flashloanVars.paraswapCallData) = _getParaswapData(multiTokenSwapData[i]);
// using ParaSwap
IERC20(flashloanVars.srcToken).safeIncreaseAllowance(flashloanVars.tokenTransferProxy, flashloanVars.srcAmount);
(flashloanVars.sent, ) = flashloanVars.paraSwapContract.call(flashloanVars.paraswapCallData);
if (!flashloanVars.sent) revert CustomError("ParaSwap deloop failed");
unchecked { i++; }
}
}
deloopInOneOrMultipleTransactions 函式分析
已經定位到了漏洞發生的位置,接下來就根據 trace 分析 deloopInOneOrMultipleTransactions 函式對四個函式的呼叫情況
-
repayAllDebtAssetsWithFlashLoan
替 0x11a8 賬戶歸還 5 USDC 的借款
-
extractAllCollaterals
傳入空陣列,跳過這函式的邏輯
-
deloopAllCollaterals
由於沒有進行引數檢查,攻擊者在這個函式中構造了兩個惡意的呼叫來獲利。
-
第一個 for 迴圈:呼叫 0x534a.executeAction 把 5 USDC 兌換成 596 WETH,並且 approve 給 ConnectorDeleverageParaswap 合約
-
第二個 for 迴圈:把 596 WETH 轉移到攻擊者控制的 0x11a8 地址
-
-
repayFlashloansAndTransferToTreasury
提供 0.9 USDC 給 0x11a8 的 AAVE 賬戶
攻擊流程分析
本次攻擊是圍繞降低 0x11a8
賬戶在 AAVE V3 上的槓桿而展開的,由於這個函式沒有對傳入的引數進行檢查,所以攻擊者構造了惡意的 multiTokenSwapData
引數在 deloopAllCollaterals
函式中對 0x534a
的 AVVE 資金進行轉移。
攻擊者構造惡意的 data
引數,解析出惡意的 multiTokenSwapData
引數
惡意的 multiTokenSwapData
引數傳入到 deloopAllCollaterals
函式中
惡意的 multiTokenSwapData
引數解析出惡意的 paraSwapContract
和 paraswapCallData
,導致了任意執行。
後記
第一次分析這個型別的攻擊事件,感覺攻擊事件還是得多分析,多積累積累經驗,擴充套件自己的視野。好好看好好學吧,之前對專案型別的接觸和理解上都有很大的侷限,還是需要多接觸一下目前經典的、熱門的專案有利於提高自己的水平,跟上市場的步伐。繼續幹唄,這事兒只能靠慢慢積累起來的。