【漏洞分析】DoughFina 攻擊事件分析:不做任何引數檢查的去槓桿合約

ACai_sec發表於2024-07-15

背景介紹

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 函式的過程。

image

ConnectorDeleverageParaswap.flashloanReq 函式

image

我們看到在 ConnectorDeleverageParaswap.flashloanReq 函式中,會呼叫 POOL.flashLoan

POOL.flashLoan 執行一個常規的閃電貸流程

  1. ConnectorDeleverageParaswap 合約從閃電貸獲取 5 USDC
  2. 呼叫 ConnectorDeleverageParaswap.executeOperation 函式
  3. 歸還 5.025 USDC
  4. handleRepayment

image

繼續跟進到 ConnectorDeleverageParaswap.executeOperation 函式,可以看到它對傳入的引數進行解析後直接呼叫 deloopInOneOrMultipleTransactions 函式

image

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 把呼叫的四個函式混在一起了不好分辨。

image

根據轉移的金額確定攻擊發生的位置,猜測這筆 WETH 的轉賬與漏洞的利用有關。

image

所以透過單步除錯的方式來檢查發生了什麼。
執行到 ConnectorDeleverageParaswap.deloopAllCollaterals 函式中時,對傳入的 multiTokenSwapData 引數進行解析,得到對應的引數: flashloanVars.srcToken, flashloanVars.destToken, flashloanVars.srcAmount, flashloanVars.destAmount, flashloanVars.paraSwapContract, flashloanVars.tokenTransferProxy, flashloanVars.paraswapCallData

其中 paraSwapContract(out4)對應的地址為 WETH 的合約地址(0xc02a),而不是進行 swap 的合約地址。

image

當執行到 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 函式對四個函式的呼叫情況

  1. repayAllDebtAssetsWithFlashLoan

    替 0x11a8 賬戶歸還 5 USDC 的借款
    image

  2. extractAllCollaterals

    傳入空陣列,跳過這函式的邏輯

    image

  3. deloopAllCollaterals

    由於沒有進行引數檢查,攻擊者在這個函式中構造了兩個惡意的呼叫來獲利。

    image

    1. 第一個 for 迴圈:呼叫 0x534a.executeAction 把 5 USDC 兌換成 596 WETH,並且 approve 給 ConnectorDeleverageParaswap 合約

      image

    2. 第二個 for 迴圈:把 596 WETH 轉移到攻擊者控制的 0x11a8 地址

      image

  4. repayFlashloansAndTransferToTreasury

    提供 0.9 USDC 給 0x11a8 的 AAVE 賬戶
    image

攻擊流程分析

本次攻擊是圍繞降低 0x11a8 賬戶在 AAVE V3 上的槓桿而展開的,由於這個函式沒有對傳入的引數進行檢查,所以攻擊者構造了惡意的 multiTokenSwapData 引數在 deloopAllCollaterals 函式中對 0x534a 的 AVVE 資金進行轉移。

攻擊者構造惡意的 data 引數,解析出惡意的 multiTokenSwapData 引數
image

惡意的 multiTokenSwapData 引數傳入到 deloopAllCollaterals 函式中
image

惡意的 multiTokenSwapData 引數解析出惡意的 paraSwapContractparaswapCallData,導致了任意執行。
image

後記

第一次分析這個型別的攻擊事件,感覺攻擊事件還是得多分析,多積累積累經驗,擴充套件自己的視野。好好看好好學吧,之前對專案型別的接觸和理解上都有很大的侷限,還是需要多接觸一下目前經典的、熱門的專案有利於提高自己的水平,跟上市場的步伐。繼續幹唄,這事兒只能靠慢慢積累起來的。

相關文章