Defi安全--Orion Protocol攻击事件分析

这篇具有很好参考价值的文章主要介绍了Defi安全--Orion Protocol攻击事件分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

其它相关文章可见个人主页

1. Orion Protocol攻击事件相关信息

2023年2月2日,在ETH和BSC上的Orion Protocol项目被攻击,这里以ETH上攻击为例:

  • 攻击合约地址:Attacker Contract Address | Etherscan
  • 攻击者地址:Orion Protocol Exploiter 2 | Address
  • 攻击交易:Ethereum Transaction Hash (Txhash) Details | Etherscan
  • Phalcon调用序列分析:0xa6f63fcb6bec881886 | Phalcon Explorer (blocksec.com)

2. Orion Protocol攻击事件分析

攻击流程详解

Eth上的攻击交易Ethereum Transaction Hash (Txhash) Details | Etherscan

从中我们可以看出,input data为单纯的函数签名,没有参数,只是调用了一个攻击函数

Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

查看对应的phalcon调用序列:

Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

  1. 先进行了一系列基础操作,对Orion Protocol项目合约进行一系列的代币授权approve()操作,如USDT和USDC等。

Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

  1. 随后我们可以看到攻击者调用了Orion Protocol的depositAsset函数,看一下该函数的源码:
    function depositAsset(address assetAddress, uint112 amount) external {
        uint256 actualAmount = IERC20(assetAddress).balanceOf(address(this));
        IERC20(assetAddress).safeTransferFrom(
            msg.sender,
            address(this),
            uint256(amount)
        );
        actualAmount = IERC20(assetAddress).balanceOf(address(this)) - actualAmount;
        generalDeposit(assetAddress, uint112(actualAmount));
    }
  1. 攻击者向orion Protocol合约转入对应数量的USDC,将该合约转账前后的代币余额,作为用户存款的数量,并调用generateDeposit函数,这一步USDC的存款是为后续的攻击做准备。
  2. 攻击者调用Uniswap V2: USDT的闪电贷函数,借出200多万个USDT

Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

  1. 调用uniswapv2的闪电贷函数,借贷对应的USDT,乐观转账,先将对应的USDT转账给了攻击者,后回调攻击者的uniswapV2Call函数
  2. 回调函数中,因为攻击者先前存入了USDC,现在攻击者调用了orion Protocol项目ExchangeWithAtomic合约中的一个函数swapThroughOrionPool,orion Protocol提供的代币交换函数,代币兑换路径为[USDC, ATK, USDT],其中ATK为攻击者提前创建的恶意代币,将USDC兑换成USDT
  3. 随后调用LibPool的doSwapThroughOrionPool的函数,再调用PoolFunctionality 合约中的doSwapThroughOrionPool函数
    function swapThroughOrionPool(
        uint112     amount_spend,
        uint112     amount_receive,
        address[]   calldata path,
        bool        is_exact_spend
    ) public payable nonReentrant {
        bool isCheckPosition = LibPool.doSwapThroughOrionPool(
            IPoolFunctionality.SwapData({
                amount_spend: amount_spend,
                amount_receive: amount_receive,
                is_exact_spend: is_exact_spend,
                supportingFee: false,
                path: path,
                orionpool_router: _orionpoolRouter,
                isInContractTrade: false,
                isSentETHEnough: false,
                isFromWallet: false,
                asset_spend: address(0)
            }),
            assetBalances, liabilities);
  1. 进一步调用PoolFunctionality 合约中的 doSwapThroughOrionPool 函数,仔细看一下函数源码,该函数进一步调用了_doSwapTokens()函数

  2. 上述代码中_doSwapTokens()函数时进行相应的输入,输出代币数量的计算,跟进该函数的实现

    function _doSwapTokens(InternalSwapData memory swapData) internal returns (uint256 amountIn, uint256 amountOut) {
        bool isLastWETH = swapData.path[swapData.path.length - 1] == WETH;
        address toAuto = isLastWETH || swapData.curFactoryType == FactoryType.CURVE ? address(this) : swapData.to;
        uint256[] memory amounts;
        if (!swapData.supportingFee) {
            if (swapData.isExactIn) {
                amounts = OrionMultiPoolLibrary.getAmountsOut(
                    swapData.curFactory,
                    swapData.curFactoryType,
                    swapData.amountIn,
                    swapData.path
                );
                require(amounts[amounts.length - 1] >= swapData.amountOut, "PoolFunctionality: IOA");
            } else {
                amounts = OrionMultiPoolLibrary.getAmountsIn(
                    swapData.curFactory,
                    swapData.curFactoryType,
                    swapData.amountOut,
                    swapData.path
                );
                require(amounts[0] <= swapData.amountIn, "PoolFunctionality: EIA");
            }
        } else {
            amounts = new uint256[](1);
            amounts[0] = swapData.amountIn;
        }
        amountIn = amounts[0];

        {
            uint256 curBalance;
            address initialTransferSource = swapData.curFactoryType == FactoryType.CURVE ? address(this)
                : OrionMultiPoolLibrary.pairFor(swapData.curFactory, swapData.path[0], swapData.path[1]);

            if (swapData.supportingFee) curBalance = IERC20(swapData.path[0]).balanceOf(initialTransferSource);

            IPoolSwapCallback(msg.sender).safeAutoTransferFrom(
                swapData.asset_spend,
                swapData.user,
                initialTransferSource,
                amountIn
            );
            if (swapData.supportingFee) amounts[0] = IERC20(swapData.path[0]).balanceOf(initialTransferSource) - curBalance;
        }

        {
            uint256 curBalance = IERC20(swapData.path[swapData.path.length - 1]).balanceOf(toAuto);
            //计算转账前的余额
            if (swapData.curFactoryType == FactoryType.CURVE) {
                _swapCurve(swapData.curFactory, amounts, swapData.path, swapData.supportingFee);
            } else if (swapData.curFactoryType == FactoryType.UNISWAPLIKE) {
            //这里的swap函数完成相应的代币兑换
                _swap(swapData.curFactory, amounts, swapData.path, toAuto, swapData.supportingFee);
            }
            //将账户余额与转账前余额相减,得到新增的金额
            amountOut = IERC20(swapData.path[swapData.path.length - 1]).balanceOf(toAuto) - curBalance;
        }

        require(
            swapData.amountIn == 0 || swapData.amountOut == 0 ||
            amountIn * 1e18 / swapData.amountIn <= amountOut * 1e18 / swapData.amountOut,
            "PoolFunctionality: OOS"
        );

        if (isLastWETH) {
            SafeTransferHelper.safeAutoTransferTo(
                WETH,
                address(0),
                swapData.to,
                amountOut
            );
        } else if (swapData.curFactoryType == FactoryType.CURVE) {
            IERC20(swapData.path[swapData.path.length - 1]).safeTransfer(swapData.to, amountOut);
        }

        emit OrionPoolSwap(
            tx.origin,
            convertFromWETH(swapData.path[0]),
            convertFromWETH(swapData.path[swapData.path.length - 1]),
            swapData.amountIn,
            amountIn,
            swapData.amountOut,
            amountOut,
            swapData.curFactory
        );
    }
  1. 这里进行相应的代币兑换,之前的兑换path为[USDC, ATK, USDT],这里通过PoolFunctionality合约中的_swap()完成相应的兑换,跟进 _swap()函数的源码
    function _swap(
        address curFactory,
        uint256[] memory amounts,
        address[] memory path,
        address _to,
        bool supportingFee
    ) internal {
        for (uint256 i; i < path.length - 1; ++i) {
            (address input, address output) = (path[i], path[i + 1]);
            IOrionPoolV2Pair pair = IOrionPoolV2Pair(OrionMultiPoolLibrary.pairFor(curFactory, input, output));
            (address token0, ) = OrionMultiPoolLibrary.sortTokens(input, output);
            uint256 amountOut;

            if (supportingFee) {
                (uint reserve0, uint reserve1,) = pair.getReserves();
                (uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
                uint256 amountIn = IERC20(input).balanceOf(address(pair)).sub(reserveInput);
                amountOut = OrionMultiPoolLibrary.getAmountOutUv2(amountIn, reserveInput, reserveOutput);
            } else {
                amountOut = amounts[i + 1];
            }

            (uint256 amount0Out, uint256 amount1Out) = input == token0 ? (uint256(0), amountOut) : (amountOut, uint256(0));
            address to = i < path.length - 2 ? OrionMultiPoolLibrary.pairFor(curFactory, output, path[i + 2]) : _to;

            pair.swap(amount0Out, amount1Out, to, new bytes(0));
        }
    }

Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

  1. path序列中的[USDC, ATK, USDT],每两个代币对之间存在一个pair合约,即USDC转到ATK,ATK转到对应的USDT,实现对应的代币兑换,攻击者创建的pair对合约,这里通过相应的计算金融模型,得到对应的转账金额,调用pair合约中的swap函数,实现相应的代币转移。

    Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

    Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

  2. 由于pair对中的swap函数,进行相应的转账,需要调用ATK代币的转账函数,ATK是攻击者部署的恶意代币,攻击者可控,攻击者这里调用自身的deposit()函数,调用ExchangeWithAtomic合约的depositAsset函数,并将闪电贷得到的200多万USDT全部转进Orion Protocol的depositAsset()函数中

  3. 这时攻击者在ExchangeWithAtomic 合约中USDT的存款被记账为了200多万,原来ExchangeWithAtomic 合约的余额为200多万,两者数值相近(攻击者设计的)

  4. 而通过swapThroughOrionPool函数中攻击者USDC兑换出多少的USDT最终是通过ExchangeWithAtomic 合约兑换前后的USDT余额计算的,相当于存入的200万USDT被认为是USDC兑换出来的,最后通过creditUserAssets 函数来更新ExchangeWithAtomic 维护的adress-balance的账本,攻击者被认为是存入了200+200万

Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约

  1. 攻击者进行相应的闪电贷还款,归还借出的200多万,获利200多万

Defi安全--Orion Protocol攻击事件分析,区块链安全,安全事件分析,Defi学习,安全,区块链,智能合约文章来源地址https://www.toymoban.com/news/detail-813128.html

  1. 调用闪电贷,借出WETH,归还USDT,实现对应的套利离场

攻击事件发生的主要原因

  • doswapThroughOrionPool 函数,兑换路径攻击者可控,代币类型攻击者可控(恶意代币)
  • 兑换后更新账本的记账方式不正确,利用前后余额计算(×)
  • 合约兑换功能的函数没有做重入保护

3. 分析Orion Protocol攻击事件所需信息

  1. 最关键的一点,重入的发生回调不在这个攻击合约之中,在攻击者创建的恶意代币合约之中(可能是这个案例的特殊情况)
  2. 普适的一点:触发恶意合约回调的功能,是在经过5次外部函数调用后,才最终调用到攻击者的恶意代币合约中的函数,在我们的工具中是无法获得这样的调用过程,全路径覆盖不太现实。

到了这里,关于Defi安全--Orion Protocol攻击事件分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2月区块链安全事件暴涨,因黑客攻击等损失金额达4亿美元

    2024年2月,各类安全事件损失金额较2023年1月大幅增加。2024年2月发生较典型安全事件超22起,因黑客攻击、钓鱼诈骗和Rug Pull造成的总损失金额达4.22亿美元,较1月上涨约103 %。其中攻击事件约3.47亿美元,增长约110%;钓鱼诈骗事件约1608万美元,下降约52%;Rug Pull事件约5938万美

    2024年03月17日
    浏览(45)
  • 【安全月报】| 3月区块链安全事件下降,因黑客攻击等损失金额达1.58亿美元

    零时科技每月安全事件看点开始了!据一些区块链安全风险监测平台统计显示,2024年3月,各类安全事件损失金额较2023年2月大幅下降。3月发生较典型安全事件超 30 起,因黑客攻击、钓鱼诈骗和Rug Pull造成的总损失金额达 1.58 亿 美元,较2月下降约 62.5% 。其中攻击事件约 1.1

    2024年04月09日
    浏览(39)
  • [区块链安全-Damn_Vulnerable_DeFi]区块链DeFi智能合约安全实战(V3.0.0)(已完结)

    很抱歉,很久没有更新了。这段时间,经历了孩子出生、出国执行项目等诸多事情,心里也比较乱,也没有思绪去完成挑战。最近总算闲下来了,不过打开一看,发现[Damn-Vulnerable-DeFi]已经执行到v3.0.0了,很多东西都发生了变化,为什么不重头做一下呢?不过这次我可能会比较

    2024年02月07日
    浏览(51)
  • 创宇区块链|Inverse Finance 安全事件分析

    北京时间 2022 年 4 月 2 日晚,Inverse Finance 借贷协议遭到攻击,损失约 1560 万美元。知道创宇区块链安全实验室第一时间跟踪本次事件并分析。 基础信息 攻击tx1:0x20a6dcff06a791a7f8be9f423053ce8caee3f9eecc31df32445fc98d4ccd8365 攻击tx2:0x600373f67521324c8068cfd025f121a0843d57ec813411661b07edc5ff781842 攻

    2023年04月08日
    浏览(37)
  • 第67篇:美国安全公司溯源分析Solarwinds供应链攻击事件全过程

    大家好,我是ABC_123 。本期继续分享Solarwinds供应链攻击事件的第4篇文章,就是美国FireEye火眼安全公司在遭受攻击者入侵之后,是如何一步步地将史上最严重的Solarwinds供应链攻击事件溯源出来的。 注: Mandiant安全公司已被FireEye收购,但是仍然可以独立运营,严格地说的,这

    2024年02月03日
    浏览(41)
  • 某60区块链安全之51%攻击实战学习记录

    1.理解并掌握区块链基本概念及区块链原理 2.理解区块链分又问题 3.理解掌握区块链51%算力攻击原理与利用 4.找到题目漏洞进行分析并形成利用 1.Ubuntu18.04操作机 python2 1.在比特币网络里,你有多少钱,不是你说了算,而是大家说了算,每个人都是公证人。 2基于算力证明进行

    2024年02月02日
    浏览(37)
  • 某60区块链安全之薅羊毛攻击实战一学习记录

    学会使用python3的web3模块 学会分析以太坊智能合约薅羊毛攻击漏洞 找到合约漏洞进行分析并形成利用 Ubuntu18.04操作机 python3 薅羊毛攻击指使用多个不同的新账户来调用空投函数获得空投币并转账至攻击者账户以达到财富累计的一种攻击方式。这类攻击方式较为普通且常见,只

    2024年02月04日
    浏览(40)
  • 某60区块链安全之薅羊毛攻击实战二学习记录

    ` 学会使用python3的web3模块 学会分析以太坊智能合约复杂场景下薅羊毛攻击漏洞及其利用 找到合约漏洞进行分析并形成利用 Ubuntu18.04操作机 python3 薅羊毛攻击指使用多个不同的新账户来调用空投函数获得空投币并转账至攻击者账户以达到财富累计的一种攻击方式。这类攻击方

    2024年02月04日
    浏览(47)
  • [区块链安全-CTF Protocol]区块链智能合约安全实战(已完结)

    这次是尝试CTF-PROTOCOL的题目,望与诸君共勉。后面应该会参考DeFiHackLabs推出对一些列攻击的POC手写和解析,同时还要参加Hackathon。大家一起努力! 题目分析: HiddenKittyCat 合约中,核心部分为: 可以知道kitty存储的位置是由 keccak256(abi.encodePacked(block.timestamp, blockhash(block.number

    2024年02月15日
    浏览(38)
  • 【信息安全案例】——网络攻击分析(学习笔记)

    📖 前言:随着信息技术的发展,网络空间的斗争可谓是兵家必争之地,网络攻击的事件层出不穷。道高一尺魔高一丈,了解常见的网络攻击类型有利于我们日后工作生活的安全稳定。 🔎 记一次Vulnstack靶场内网渗透(二) 🕤 1.2.1 欺骗攻击 利用TCP/IP协议本身的一些缺陷对

    2024年02月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包