{"content":{"title":"ORT Token被攻击事件分析","body":"## 基本信息\r\n\r\n- 黑客EOA地址：0x9bbd94506398a1459f0cd3b2638512627390255e\r\n- 攻击合约：0x0effeca3dbcbcda4d5e4515829b0d42181700606、0xdd87d807774c8aa9d70fc6af5912c97fadbf531b\r\n- 受攻击合约Proxy：0x6f40a3d0c89cffdc8a1af212a019c220a295e9bb\r\n- 受攻击合约：0x26bc1245b8476086e85553e60ee5e3e59fed9be0\r\n\r\n## 攻击细节\r\n\r\n攻击者部署了2个合约，2个攻击合约相似度高，以其中一个攻击合约为例，攻击者主要的攻击步骤为三步：\r\n\r\n1. 攻击者使用EOA账户去调用攻击合约的`invest`方法\r\n2. 攻击者使用EOA账户去调用攻击合约的`Withdraw`方法\r\n3. 攻击者使用EOA账户去调用攻击合约的`WithdrawToken`方法\r\n\r\n\r\n![20230118151005.png](https://img.learnblockchain.cn/attachments/2023/01/aBKLgvC963c79bbd4d51d.png)\r\n\r\n\r\n![20230118143557.png](https://img.learnblockchain.cn/attachments/2023/01/H3XRT5Jh63c79be67b4c4.png)\r\n\r\n分别对应选取一笔交易进行分析，先来看调用`invest`方法的这笔交易\r\n\r\nhttps://bscscan.com/tx/0x63e8185c867de4c0d09b8df7813647d0aca0596a0e786cd8c6f4202053edc0bc\r\n\r\n其实际调用了被攻击合约的`invest`方法：\r\n![20230118144553.png](https://img.learnblockchain.cn/attachments/2023/01/sNBi2iX463c79bdf04f1d.png)\r\n\r\n参照对应的StakingPool中的invest合约代码，攻击者给形参`end_date`传入了0，给形参`qty_ort`传入了1，过了`require(qty_ort > 0, \"amount cannot be 0\")`的判断，之后由于`end_date`输入了意外之外的值0，直接过了`if...eles if...`，并调用内部`_Check_reward`方法开始计算奖励，并写入结构体中。\r\n\r\n```\r\n    function invest(uint256 end_date, uint256 qty_ort) external whenNotPaused {\r\n        require(qty_ort > 0, \"amount cannot be 0\");\r\n        //transfer token to this smart contract\r\n        stakeToken.approve(address(this), qty_ort);\r\n        stakeToken.safeTransferFrom(msg.sender, address(this), qty_ort);\r\n        //save their staking duration for further use\r\n        if (end_date == 3) {\r\n            end_staking[msg.sender] = block.timestamp + 90 days;\r\n            duration[msg.sender] = 3;\r\n        } else if (end_date == 6) {\r\n            end_staking[msg.sender] = block.timestamp + 180 days;\r\n            duration[msg.sender] = 6;\r\n        } else if (end_date == 12) {\r\n            end_staking[msg.sender] = block.timestamp + 365 days;\r\n            duration[msg.sender] = 12;\r\n        } else if (end_date == 24) {\r\n            end_staking[msg.sender] = block.timestamp + 730 days;\r\n            duration[msg.sender] = 24;\r\n        }\r\n        //calculate reward tokens  for further use\r\n        uint256 check_reward = _Check_reward(duration[msg.sender], qty_ort) /\r\n            1 ether;\r\n        //save values in array\r\n        tokens_staking.push(\r\n            staking(\r\n                msg.sender,\r\n                qty_ort,\r\n                end_staking[msg.sender],\r\n                duration[msg.sender],\r\n                true,\r\n                check_reward\r\n            )\r\n        );\r\n        //save array index in map\r\n        uint256 lockId = tokens_staking.length - 1;\r\n        userStake[msg.sender].push(lockId);\r\n\r\n        emit Invest(\r\n            msg.sender,\r\n            lockId,\r\n            end_staking[msg.sender],\r\n            duration[msg.sender],\r\n            qty_ort,\r\n            check_reward\r\n        );\r\n    }\r\n```\r\n\r\n\r\n跟进计算奖励的`_Check_reward`方法，内部写了一个`if...else if...`来计算奖励，但由于攻击者传入的`end_date`为0，因此`duration[msg.sender]`对应的值也为0，导致`_Check_reward`直接返回了total_percent，从Events事件可以看到total_percent值为8930620160000000000000000：\r\n\r\n\r\n![20230118145219.png](https://img.learnblockchain.cn/attachments/2023/01/Qd2oknCe63c79ca7c4b9a.png)\r\n\r\n以上就是调用`invest`方法的分析，接着再来看下`withdraw`的这笔交易：\r\nhttps://bscscan.com/tx/0xd90f2ccfcd0fdbd002af7b21b51732a7a08d0bd3af2d298ec275062a11eb3019\r\n\r\n![20230118150126.png](https://img.learnblockchain.cn/attachments/2023/01/vWhaAA6k63c79dff3cfef.png)\r\n\r\n实际是调用了被攻击合约的withdrawAndClaim方法，其会调用内部2个方法`_withdraw`、`_claim`，需要传入的是lockId，lockId，在`invest`交易的Log日志中有输出。\r\n\r\n```\r\n    function withdrawAndClaim(uint256 lockId)\r\n        external\r\n        nonReentrant\r\n        whenNotPaused\r\n        onlyStakeOwner(lockId)\r\n    {\r\n        _withdraw(lockId);\r\n        _claim(lockId);\r\n    }\r\n```\r\n\r\n分析_withdraw方法其作用是用于领取之前质押进去的Token。\r\n\r\n```\r\n    function _withdraw(uint256 lockId) internal {\r\n        require(tokens_staking[lockId].balances > 0, \"not an investor\");\r\n        require(\r\n            block.timestamp >= tokens_staking[lockId].end_staking,\r\n            \"too early\"\r\n        );\r\n        //Change status of invester for reward\r\n        uint256 invested_balance = 0;\r\n        invested_balance = tokens_staking[lockId].balances;\r\n        tokens_staking[lockId].changeClaimed = false;\r\n        tokens_staking[lockId].balances = 0;\r\n        tokens_staking[lockId].duration = 0;\r\n        tokens_staking[lockId].end_staking = 0;\r\n        //transfer back amount to user\r\n        stakeToken.safeTransfer(msg.sender, invested_balance);\r\n\r\n        emit Withdraw(msg.sender, lockId, invested_balance);\r\n    }\r\n```\r\n\r\n分析_claim方法其作用是用于领取奖励。\r\n\r\n```\r\n    function _claim(uint256 lockId) internal {\r\n        require(tokens_staking[lockId].check_claim > 0, \"No Reward Available\");\r\n        require(\r\n            tokens_staking[lockId].changeClaimed == false,\r\n            \"Already claimed\"\r\n        );\r\n        //change status of invested user\r\n        tokens_staking[lockId].changeClaimed = true;\r\n        uint256 claimed_amount = 0;\r\n        claimed_amount = tokens_staking[lockId].check_claim;\r\n        tokens_staking[lockId].check_claim = 0;\r\n        //mint new ort token\r\n        rewardToken.mint(msg.sender, claimed_amount);\r\n\r\n        emit Claim(msg.sender, lockId, claimed_amount);\r\n    }\r\n```\r\n\r\n最后调用`withdrawToken`方法将攻击合约中的Token全部取出。\r\n\r\nhttps://bscscan.com/tx/0x7aac05fecd19b19c28929b29262fb848eb00323d9f2b496d422e795fd9869f70\r\n\r\n\r\n![20230118150225.png](https://img.learnblockchain.cn/attachments/2023/01/YtWncOLn63c79eee5f3ec.png)\r\n\r\n攻击者循环利用3步，将获得的Token通过Pancake砸盘获利。\r\nhttps://bscscan.com/tx/0xa68442bd5ae35711e4e7f26d02787a3d2aed9db7084f48e3b7ed722a3487c629\r\n![20230118153355.png](https://img.learnblockchain.cn/attachments/2023/01/tSz4ak1z63c7a0ef94238.png)\r\n\r\n## 参考链接\r\nhttps://twitter.com/BeosinAlert/status/1615197760546037760"},"author":{"user":"https://learnblockchain.cn/people/10423","address":"0x5ab4713dF76002d9a97708fC47482EF10A990a47"},"history":"QmdnZx7ahfR1em7WoGtXZZbv15TgsmxeZMpBLDuH8yti3D","timestamp":1674033769,"version":1}