{"content":{"title":"【深入解读】FTX交易所免手续费漏洞致使被薅20W刀XEN的羊毛案","body":"被朋友Q到近期火热的羊毛事件，截止目前，不仅是**黑客获利超20W刀，FTX损失108+个ETH**，合计有38名同样思路的攻击者部署合约发起攻击。\r\n\r\n本文从技术维度出发，深入分析此利用FTX交易所免手续费提币的漏洞，结合智能合约回调发起的攻击方式，并通过样例代码复现实现原理。\r\n\r\n由于FTX已经通过人工审计针对攻击者进行惩罚，该漏洞处于风险可控阶段。切勿尝试可能导致封号没收质押物。\r\n\r\n## 1、背景\r\n### 1.1 XEN是什么？\r\n是近期大火的一个XEN币，到10-15为止已有超过120W笔交易，其实笔者对这类缺乏长期价值对Web3毫无建设性意义的项目一直没什么兴趣，因为他的机制就是只要发起的交易消耗了多少的GAS，就可以铸造出一定数量的XEN币，而众所周知Etherscan有针对gas消耗的排行榜\r\n\r\n可以看到真正出色的项目往往由于服务用户多交易量大，所以gas消耗高排名靠前，仿佛成了另一种的应用商店热门榜单，而XEN一举通过“冲票“成了冠绝以太坊整个生态的Top1，且等于其他好项目的总和。\r\n\r\n![Untitled.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/10\/xqmgllNe634a9abcae25c.png)\r\n\r\n\r\n\r\n\r\n可拓展阅读：[当我们在看Etherscan的时候,到底在看什么?](https:\/\/learnblockchain.cn\/article\/4137)\r\n\r\n### 1.2 受害方FTX交易所\r\n本次被攻击的也正是其免费提币的优惠活动，在平台有质押且有一定交易记录后即可发起免费提币，而提币会受制于之前交易量（因此本文仅出于科普分析攻击手法，请勿模仿，易于被FTX官方封号没收质押资产）\r\n\r\n\r\n![Untitled (1).png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/10\/O5aPXoso634a9ada65935.png)\r\n\r\n\r\n\r\n\r\n\r\n### 1.3 链上数分结果\r\n其实mirror上爆出的还不是最大的攻击者，而此攻击手法最早出现在10-10号，截止10-15号，合计类似逻辑的**攻击地址有38个，合计1.45W笔攻击**（无法判断地址背后是否为相同攻击者）。\r\n\r\n计算依据：FTX热钱包单笔转移gas消耗大于5W，且to地址是合约地址的交易。\r\n\r\n下图为其中top10的攻击者，其交易数占总攻击数的80%，致使FTX手续费损失86个ETH\r\n\r\n笔者通过对其交易的gas消耗总值核算后，**得出FTX本次损失总值为：108.19个ETH**\r\n\r\n合计铸造出XEN约24亿个。按14号日常价格估算的话，则**黑客总收益在24W美金以上**\r\n\r\n\r\n\r\n![Untitled (2).png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/10\/0CMSqXDj634a9b08a5cd5.png)\r\n\r\n\r\n\r\n详细数据可<十四君>公众号后台输入”FTX与XEN”获得\r\n\r\n\r\n\r\n\r\n\r\n## 2、黑客攻击流程分析\r\n### 2.1 核心原理\r\n智能合约的fallback\/receive可任意执行逻辑。\r\n\r\n任何一个合约都有默认的fallback函数，典型的功能就是让合约可以接收以太币并对其做出反应，这也是代币型合约用来拒绝转账、发出事件或转发以太币的典型模式。后来更多场景是应用在代理升级模式（合约部署链上本身不可更改，但可以修改指向新的合约，从而实现一定程度上的升级）\r\n\r\n总之就是，一笔指向合约地址的交易，如果没有匹配到对应执行的函数，就必然会执行fallback函数，而fallback可以将输入参数指向另一个合约地址，从而执行对应的逻辑。\r\n\r\n参考：https:\/\/blog.soliditylang.org\/2020\/03\/26\/fallback-receive-split\/\r\n\r\n### 2.2 攻击流程\r\n其实看完手法核心，已经很明显了\r\n\r\n1. 黑客先部署了一个攻击合约0xCba9b1\r\n2. 然后利用FTX的交易免费提币功能\r\n3. 让FTX的热钱包0xc098b2，发起了一笔指向攻击合约的提币\r\n4. 导致交易触发指向XEN合约的Mint函数调用\r\n5. 由于XEN合约可以设置Mint出代币的收益方，从而将代币转入黑客地址\r\n\r\n\r\n![Untitled (3).png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/10\/BuBYkfX5634a9b3f0e08a.png)\r\n\r\n\r\n\r\n\r\n### 2.3 手法还原\r\n其实任意fallback非常好触发，咱们通过现场手搓实现下，当然并不是MintXen，而是临时随意的一个20token来示意。\r\n\r\n下文便是最简单的一个ERC20代币了，任何人均可执行mint函数，雷同于XEN了\r\n\r\n对于ERC20\/721实现原理可拓展阅读：【源码解读】你买的NFT到底是什么？\r\n\r\n\r\n```\r\nimport \"@openzeppelin\/contracts\/token\/ERC20\/ERC20.sol\";\r\ncontract token20 is ERC20 {\r\n    constructor() ERC20(\"Gold\", \"GLD\") {}\r\n    function mint(address to,uint256 amount) public {\r\n        _mint(to,amount);\r\n    }\r\n}\r\n```\r\n\r\n\r\n\r\n而攻击合约也很简单，设置写死要调用Mint的XEN合约地址以及黑客收益的地址。\r\n\r\n\r\n```\r\ninterface IERC20 {function mint(address to,uint256 amout) external ;}\r\ncontract attack{\r\n    address ERC20Addr = 0xd9145CCE52D386f254917e481eB44e9943F39138;\r\n    address myAddr = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;\r\n    receive() external payable {\r\n        IERC20(ERC20Addr).mint(myAddr,1e18);\r\n        selfdestruct(payable(myAddr));\r\n    }\r\n}\r\n```\r\n\r\n\r\n\r\n可以看到实验中，对此攻击合约发起的任意一笔交易，即会触发了receive，且myAddr的GLD余额增加1e18个，**当然并不能拿着这个代码就去复现黑客的实现了**，因为要铸造更多的GEX还得增加工厂合约部署的逻辑，即能提高gas消耗也吻合XEG的mint管理。\r\n\r\n![Untitled (4).png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/10\/FMValM9d634a9b679d9f1.png)\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n## 3、总结-从攻击事件看“元交易”\r\n其实如果不是黑客本身知道FTX有免费提币优惠，且其提币的交易的gasLimit设置为固定值50W，则**很难发起这样的攻击**，因为依据以太坊黄皮书，普通转账也仅仅需要2.1W的gas即可。\r\n\r\n黑暗森林的web里知**其雄守其雌**，这样的攻击从历史进程来看，其实更有警示性意义\r\n\r\n笔者想谈谈元交易的发展\r\n\r\n元交易是来自于Christian Lundkvist教授在2015年的一个设想\r\n\r\n如今上手 Dapp 实在是太麻烦了，以太坊生态若想普及，就应该允许新用户直接使用其功能，而不是先安排几座大山让用户翻山越岭。这意味着需要为新来的用户垫付 Gas 费用。当前的以太坊协议并没有提供原生方法来实现这一点。然而，得益于公\/私密钥对，用户可以通过对元交易 进行签名并证明所有权。\r\n\r\n相信未来元交易终会成为应用主流，本次的FTX代付gas执行免费提币转账还只是元交易的某种小小（伪）实现，**但只有安全+无感才能迎接全民低成本上链时代的到来（而非低代币gas价格）**，为此安全与风控都需要特别注意，这也是笔者分析安全案件的初衷。\r\n\r\n\r\n\r\n欢迎你从后台提交web3行业问题探讨\r\n\r\n点赞关注十四，用技术视角带给你价值"},"author":{"user":"https:\/\/learnblockchain.cn\/people\/6626","address":null},"history":"QmRpJpVeEtDmsFdB39Y7eDEFrZj9E1xe9r383qxvZwaY5A","timestamp":1665967893,"version":1}