【漏洞分析】DoughFina 攻击事件分析:不做任何参数检查的去杠杆合约

doughfina · 浏览次数 : 50

小编点评

2024年7月12日,DoughFina协议遭受了黑客攻击,主要原因是ConnectorDeleverageParaswap合约没有对输入参数进行检查,导致攻击者可以利用这一漏洞窃取DSA合约的资金。此次攻击涉及到的合约有:DSA(被攻击地址):0x534a,攻击合约:0x11a8,ConnectorDeleverageParaswap:0x9f54e8eaa9658316bb8006e03fff1cb191aafbe6。 攻击交易分析: 1. 攻击者在发起攻击之前,先利用闪电贷的资金帮0x534a归还了他的借款938566 USDC。 2. ConnectorDeleverageParaswap.flashloanReq函数中调用POOL.flashLoan执行常规的闪电贷流程。 3. ConnectorDeleverageParaswap.executeOperation函数对传入的参数进行解析,然后调用deloopInOneOrMultipleTransactions函数。 4. deloopInOneOrMultipleTransactions函数中,攻击者构造了两个恶意的调用来获利:第一个for循环调用0x534a.executeAction把5USDC兑换成596WETH,并且批准给ConnectorDeleverageParaswap合约;第二个for循环把596WETH转移到攻击者控制的0x11a8地址。 漏洞利用方式:攻击者通过构造恶意的multiTokenSwapData参数,在deloopAllCollaterals函数中对0x534a的AVVE资金进行转移。攻击者构造恶意的data参数,解析出恶意的multiTokenSwapData参数,恶意的multiTokenSwapData参数传入到deloopAllCollaterals函数中,恶意的multiTokenSwapData参数解析出恶意的paraSwapContract和paraswapCallData,导致了任意执行。 修复建议:在 ConnectorDeleverageParaswap合约中加强对输入参数的检查,避免类似的漏洞被利用。

正文

背景介绍

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

后记

第一次分析这个类型的攻击事件,感觉攻击事件还是得多分析,多积累积累经验,扩展自己的视野。好好看好好学吧,之前对项目类型的接触和理解上都有很大的局限,还是需要多接触一下目前经典的、热门的项目有利于提高自己的水平,跟上市场的步伐。继续干呗,这事儿只能靠慢慢积累起来的。

与【漏洞分析】DoughFina 攻击事件分析:不做任何参数检查的去杠杆合约相似的内容:

【漏洞分析】DoughFina 攻击事件分析:不做任何参数检查的去杠杆合约

背景介绍 2024 年 7 月 12 日,DoughFina 协议遭受了黑客攻击,造成本次攻击的主要原因是 ConnectorDeleverageParaswap 合约没有对输入参数进行检查,且该合约为 DSA 合约的 owner。攻击者可以构造恶意参数窃取 DSA 合约的资金。 攻击交易 http

【漏洞分析】Li.Fi攻击事件分析:缺乏关键参数检查的钻石协议

背景信息 2024 年 7 月 16日,Li.Fi 协议遭受黑客攻击,漏洞成因是钻石协议中 diamond 合约新添加的 facet 合约没有对参数进行检查,导致 call 函数任意执行。且 diamond 合约拥有用户的 approve,所以攻击者可以构造恶意参数对用户资金进行转移。 攻击交易ht

有隙可乘 - Android 序列化漏洞分析实战

本文主要描述了FileProvider,startAnyWhere实现,Parcel不对称漏洞以及这三者结合产生的漏洞利用实战,另外阐述了漏洞利用的影响和修复预防措施,这个漏洞波及了几乎所有的Android手机,希望能带给读者提供一些经验和启发。

一文详解SpEL表达式注入漏洞

摘要:本文介绍了SpEL表达式以及常见的SpEL注入攻击,详细地介绍了部分漏洞攻击实例以及常用的漏洞检测与防御手段。 本文分享自华为云社区《SpEL表达式注入漏洞分析、检查与防御》,作者:华为云软件分析Lab。 在安全角度来看外部来源的数据,均应视为不可信数据,对外部数据,其包含的所有信息都须经过校

Fastjson基础环境配置与Java基础概念

Preface 此篇系列文章将会从 Java 的基础语法开始,以 Fastjson 的各个反序列化漏洞分析为结尾,详细记录如何从一个具有基础面向对象编程但毫无 Java 基础的小白成长为了解 Fastjson 的各个漏洞并能够熟练利用的网络安全人员。 环境配置 我们使用 IDEA 作为开发的 IDE

4.4 x64dbg 绕过反调试保护机制

在Windows平台下,应用程序为了保护自己不被调试器调试会通过各种方法限制进程调试自身,通常此类反调试技术会限制我们对其进行软件逆向与漏洞分析,我们以第一种`IsDebuggerPresent`反调试为例,该函数用于检查当前程序是否在调试器的环境下运行。函数返回一个布尔值,如果当前程序正在被调试,则返回True,否则返回False。函数通过检查特定的内存地址来判断是否有调试器在运行。具体来说,该

4.9 x64dbg 内存处理与差异对比

LyScript 插件中针对内存读写函数的封装功能并不多,只提供了最基本的`内存读取`和`内存写入`系列函数的封装,本章将继续对API接口进行封装,实现一些在软件逆向分析中非常实用的功能,例如ShellCode代码写出与置入,内存交换,内存区域对比,磁盘与内存镜像比较,内存特征码检索等功能,学会使用这些功能对于后续漏洞分析以及病毒分析都可以起到事半功倍的效果,读者应重点关注这些函数的使用方式。

10.5 认识XEDParse汇编引擎

XEDParse 是一款开源的x86指令编码库,该库用于将MASM语法的汇编指令级转换为对等的机器码,并以XED格式输出,目前该库支持x86、x64平台下的汇编编码,XEDParse的特点是高效、准确、易于使用,它可以良好地处理各种类型的指令,从而更容易地确定一段程序的指令集。XEDParse库可以集成到许多不同的应用程序和工具中,因此被广泛应用于反汇编、逆向工程、漏洞分析和入侵检测等领域。XED

逻辑漏洞挖掘之XSS漏洞原理分析及实战演练

本系列文章旨在揭秘逻辑漏洞的范围、原理及预防措施,逐步提升大家的安全意识。作为开篇第一章,本文选取了广为熟知的XSS逻辑漏洞进行介绍。

一篇文章了解DongTai IAST

文章转载自DongTai官网,只限个人学习使用。 简介 洞态 IAST 是一个完全开源的 IAST 项目,它使用应用程序运行时数据流进行分析从而识别可被利用的安全漏洞,再按风险优先级的提供已验证漏洞列表功能,协助开发人员实时的代码修复。 主要功能:全面精准的应用漏洞测试、开源组件漏洞和风险分析、应用