此篇文章由 Cobo 区块链安全团队供稿,团队成员来自知名安全实验室,有多年网络安全与漏洞挖掘经验,曾协助谷歌 、微软等厂商处理高危漏洞并获致谢,在微软 MSRC 最有价值安全研究员Top 榜单中取得卓越的成绩。团队目前重点关注智能合约安全、DeFi 安全等方向,研究并分享前沿区块链安全技术。我们也希望对加密数字货币领域有研究精神和科学方法论的终身迭代学习者可以加入我们的行列,向行业输出思考洞察与研究观点!此篇是CoboLabs的第9篇文章。
Treasure DAO NFT市场被攻击
3月3日,Treasure DAO 的 NFT 市场遭受攻击,攻击者从市场中盗取了100 多个 NFT。但事件发生几小时后,攻击者将盗取的NFT归还。
NFT 市场的 TreasureMarketplaceBuyer.buyItem 函数接口支持 ERC721 和 ERC1155 两种 NFT 的交易,并可传入 quantity 参数表示购买 NFT 的数量(针对 ERC1155 来说),计算总费用时,会通过数量*单价的形式进行计算。
由于合约代码未对用户传入的 quantity 参数进行校验,用户可以将 quantity 设置为 0,使得后续计算所需花费为 0。而 ERC721 Token 具有唯一性,所以代码不会对传入的 quantity 进行处理,在 quantity 为 0 时 TreasureMarketplace.buyItem 后续对于存量和 quantity 的检查也能通过。最终结果攻击者可以免费从市场中买到任意 ERC721 NFT 商品。
另外,如果攻击者通过查询对应的 tokenid 的拥有者,可以直接调用 TreasureMarketplace.buyItem 函数绕过 TreasureMarketplaceBuyer 合约直接购买。
整个攻击流程中,market 只做为中间商,除了没有收到手续费外并没有承担其他经济上的损失,最终的损失由卖家承担。
CoboComment:
合约在实现处理不同代币类型的接口时,需要充分考虑不同代币标准的区别。历史上合约因处理 ERC20 与原生代币、ERC777、ERC2612 不同标准不当均产生过安全问题。开发者谨慎考虑边界情况,并组织代码审计,毕竟不是每次被盗取的资产都会被返还。
R
e
f
e
r
e
n
c
e
:
https://mp.weixin.qq.com/s/E7dfEDO0R7SZK16xUhMzag
https://mp.weixin.qq.com/s/SEbXWmugJBz0C00vyzYcCw
Bacon Protocol 重入攻击事件
3月5日,抵押借贷协议 Bacon Protocol 遭到重入攻击,损失约 100 万美元。
Bacon Protocol 的 bHome 代币用于作为用户存入资产凭证,该 Token 实现 ERC777 标准接口。当进行转账时,会调用 ERC777 标准规定的回调函数 tokensReceived。攻击者在自己实现的 tokensReceived 函数可再次调用 Bacon Protocol 的 lend 函数,造成重入攻击。
由于生成的 bHome 代币计算公式中会记录用户的累计存款,并根据累计存款来计算生成的 bHome 代币数量,而这一变量的更新则是在调用完回调函数后进行的。因此利用重入漏洞,可以使合约过量更新攻击者 bHome 的 balance,使攻击者在每次存款时得到比预期更多的 bHome 代币,以此获利。
CoboComment:
利用 ERC777 代币回调函数进行重入攻击在历史上出现过多次同类问题,项目开发者在采用这一代币标准时就应重点检查代码是否可以处理回调中重入的情况。
或者使用 OpenZeppelin ReentrancyGuard 进行防护也能防范一些重入攻击的实施。
另外值得一提的是,本次攻击被 BlockSec Team 检测到。
他们通过部署同样合约并用 flashbot 抢跑的方式先于攻击者提前进行白帽攻击,帮助项目方挽回了一部分的损失。
随着此类系统发展的更加成熟,可预见的是,未来攻击者也将开始逐步使用 flashbot 执行攻击交易以进行对抗。
R
e
f
e
r
e
n
c
e
:
https://www.tofreedom.me/bacon-protocolerc777
https://mp.weixin.qq.com/s/o41Da2PJtu7LEcam9eyCeQ
Fantasm Finance 攻击事件3月9日,Fantom 链上 DeFi 项目 Fantasm Finance 遭到攻击,损失约 270 万美金。漏洞点发生在抵押池 Pool 合约的 mint 函数,mint 函数会根据用户传入的 FSM 代币和 FTM 铸造对应的 xFTM 代币。用户调用 mint 函数应该按一定的抵押比例转入 FSM 和 FTM(缺少的 FSM 也可用 FTM 补齐)。但实际合约代码并没有校验用户转入的 FTM 数量,从而让攻击者在只转入 FSM 不转入 FTM的情况也能铸造 xFTM 代币,从而可获得 (1-collateralRatio) 倍数量的额外收益。CoboComment:从文档和公开信息中可以看到,Fantasm 在 3 月 1 日上线,3 月 5 日提交代码给 Obelisk 进行审计,3 月 9 日被攻击。互联网行业的“不管有没有 bug 先上线再说” 的恶习似乎也传到了区块链世界,在新项目中这种先上线后审计的现象屡见不鲜。在 DeFi 上安全漏洞的代价要远高于传统互联网 C 端产品。希望项目方本着对用户负责的态度务必先再完成代码审计后再进行上线。对于普通用户来说,遇到类似的情况则要保持谨慎态度,避免造成资产损失。Reference:https://twitter.com/nipun_pit/status/1501816047711580160https://www.tofreedom.me/fantasm-financehttps://medium.com/@fantasmfinance/fantasm-finance-post-mortem-exploit-09-march-2022-daf48ead016fParaluni 闪电贷重入攻击事件3月13日,Parallel Universe 在 BSC 发布的 Paraluni 项目遭到重入攻击,损失超过170万美元。Paraluni 的 Masterchef 合约实现 depositByAddLiquidity 方法,允许用户转入两种 token 的地址,由合约组成 LP token 并进行 deposit。合约没有校验传入的 token 是否与 deposit pool 中的 LP token 的原始 token 是否一致,只是检查合约自身 LP token 数量有没有增多以判断用户是否进行 LP token 的抵押。在这种情况下,攻击者自行伪造了 2 个 ERC20 token,并调用 depositByAddLiquidity。伪造的 ERC20 token 中重写了 transferFrom 方法,在 transferFrom 函数内调用合约的 deposit 函数(这里形成重入攻击)。deposit 函数完成后,合约自身 LP token 数量会增多,从而回到 depositByAddLiquidity 函数后,会再次计算一次 deposit 数量,导致重复计算 LP token。攻击者通过闪电贷借入 BUSD 和 USDT,利用上述方式 deposit 再 withdraw,即可以获得借入资产相同的获利。CoboComment:代码层面看,漏洞产生的原因有二:一,depositByAddLiquidity 没有对传入的 token 参数与 pool 的匹配性进行检查,通过传入伪造 token 合约可以实现任意合约调用;二,对于 deposit 等关键方法,没有使用 OpenZeppelin ReentrancyGuard 进行防护,从而利用一进行重入攻击。从项目运营角度来说,项目方没有通过知名安全厂商进行安全审计,且没有披露完整的审计报告。对于普通用户而言,尽管第三方审计不能完全保证项目代码安全,对于没有经过知名厂商安全审计的项目,仍然需要保持谨慎态度。Reference:https://mp.weixin.qq.com/s/a5fFI5sFNAyuDxGqTFmC2Ahttps://mp.weixin.qq.com/s/BHViq_7vBUJDWIsMgGDU4whttps://bscscan.com/address/0xa386f30853a7eb7e6a25ec8389337a5c6973421d#codeDeus Finance遭闪电贷攻击3月15日,部署在 Fantom 链上的 Defi 协议 Deus Finance 遭闪电贷攻击,攻击者获利约 300 万美元。Deus Finance 的价格预言机直接利用交易池两代币余额与总流动性比值计算价格,导致攻击者可以通过闪电贷从交易池中借取大量的 DEI Token 来操纵币价,随后攻击者以低价清算其他用户的抵押资产,以此获利。事件发生后,Deus Finance 项目方已经将原预言机修改,并且展开了调查工作。CoboComment:Deus Finance 使用交易池的实时代币余额进行报价,属于典型的易受闪电贷进行价格操作的预言机模型。攻击者利用此预言机控制攻击进行恶意清算,造成普通用户资产受损。对于投资者,在投资抵押借贷类项目时,建议关注项目文档和代码中使用的预言机模型,避免遭受预言机控制导致的恶意清算。目前各类预言机模型中:ChainLink 等去中心化预言机通常认为最为可靠;Uniswap V2/V3 的 TWAP 预言机也会受大资金的操纵,但有延迟报价机会,因此不受闪电贷操纵;直接使用交易池实时余额进行报价则非常容易遭受预言机操纵攻击。Reference:https://twitter.com/peckshield/status/1503632734299701250https://cryptopotato.com/3-million-in-dai-and-eth-stolen-from-deus-finance-in-the-latest-defi-hack/Hundred FInance 重入攻击事件3月16日,xDai 链上借贷项目 Hundred FInance 遭重入攻击,项目方损失约 2363 ETH。漏洞成因是 Hundred FInance 在实现借款函数 borrowFresh 时,转账操作是在记账操作之前,且没有使用 ReentrancyGuard 进行重入保护,因此存在重入攻击的风险。xDai 链上的 WETH、USDC 等币均使用 PermittableToken 合约模板。该模板中实现了对 ERC677 标准的支持。当转账收款地址是合约时,会自动回调 onTokenTransfer 函数。结合上述两个条件,攻击者得以进行重入攻击。攻击者首先通过闪电贷获得攻击资金,在攻击合约的 onTokenTransfer 函数中重复调用 borrow 函数,由于记账操作在转账操作后,所以攻击者可以通过一份抵押资产反复使用,贷出远超过抵押金额的贷款,以此获利。CoboComment:3 月出现了多起重入攻击事件。重入攻击漏洞的存在通常需要满足 3 个条件:(1)存在可触发重入的调用,如:合约使用 .call 底级调用进行转账;存在回调函数,如ERC777 或 ERC677 标准;(2)合约的状态修改代码在重入代码之后;(3)没有使用 OpenZeppelin ReentrancyGuard 进行保护。开发者应该高度关注此类问题,尤其是项目要支持 ERC777 或 ERC677 资产时,涉及资产转移、记账功能等关键函数都需要考虑是否有重入的可能,防患于未然。Reference:https://mp.weixin.qq.com/s/tlXn3IDSbeoxXQfNe_dH3Ahttps://www.anquanke.com/post/id/270609https://blockscout.com/xdai/mainnet/address/0xf8D1677c8a0c961938bf2f9aDc3F3CFDA759A9d9/contracts
Li Finance 攻击事件
3月20日,Li Finance 发生攻击事件,攻击者利用合约漏洞从多个用户钱包中盗取了总价值约60万美元的多种虚拟资产。事件发生后官方第一时间修补了漏洞并且补偿了用户的损失。
漏洞点发生在交易池的 swap 函数,协议设计初衷是为了能够同时处理多笔swap操作,在合约进行 swap 时允许根据用户自定义传入的 calldata 进行底层调用。攻击者利用这一功能构造 calldata ,使协议可以调用 token 的 transferFrom 函数,将其他用户 approve 给协议的资产盗走。
CoboComment:
使用用户可控的参数进行合约调用是相当危险的操作,相当于传统安全领域中代码注入漏洞。开发者应尽量使用特定数据结构进行功能封装,避免将这类底层操作权限直接暴露给用户。
Reference:
https://cointelegraph.com/news/li-finance-protocol-loses-600-000-in-latest-defi-exploit
https://knownseclab.com/news/623842bed5b228005a55cd57
Compound Finance 修复严重漏洞
3月22日,ChainSecurity 发文称 Compound Finance 的 CToken 合约对 TrueUSD(TUSD) 代币的支持存在安全漏洞。根据 OpenZeppelin 的分析,此漏洞除 Compound 外也可能对多达 30 个协议造成影响。如被利用,可能造成上百万美金的损失。
TUSD 实现了 DelegateERC20 机制,支持将所有与原始合约 0x8dd5fbCe2F6a956C3022bA3663759011Dd51e73E 交互 delegate 到当前合约 0x0000000000085d4780B73119b644AE5ecd22b376 上来(注意与 Proxy 机制相区别,这里 delegate 机制所有 storage 修改都在 0x0000..b376 上完成)。最终导致 TUSD 存在两个合约入口,即通过两个合约地址,都可以操纵 TUSD 资产。由于许多合约代码都默认不同合约地址的 ERC20 为不同的两种资产,并要一些权限校验位置通过合约地址进行校验。这种不一致导致许多合约在处理 TUSD 时可能存在问题。
其中 Compound 的 CToken 就设计了sweepToken 接口允许将 underlying资产以外的 Token 转移给管理员(用以回收其他错误转入的 Token),这里就通过比较合约地址与 underlying 是否一致进行校验。因此攻击者可以传入 0x8dd5..e73E 地址绕过校验,将池中的 TUSD 资产转移给管理员。利用这种方法,攻击者可任意移除借贷池中的 TUSD 流动性,从而操纵 exchangeRate 套利或者进行恶意清算获利。
CoboComment:
TUSD 的 DelegateERC20 机制和 CToken 的 sweepToken 接口在单独工作时均不会产生任何问题。但二者组合时就会因兼容性问题产生安全风险。项目方对接入新资产时将仔细审计 Token 协议代码中是否有与自身设计不兼容的情况。
目前 TUSD 官方已经升级,移除了对 0x8dd5fbCe2F6a956C3022bA3663759011Dd51e73E DelegateERC20 的支持,发向此合约的所有 ERC20 交易都将 revert。用户日常使用时请注意使用 TUSD 主合约 0x0000000000085d4780B73119b644AE5ecd22b376。
Reference:
https://medium.com/chainsecurity/trueusd-compound-vulnerability-bc5b696d29e2
https://blog.openzeppelin.com/compound-tusd-integration-issue-retrospective/
One Ring Finance 遭闪电贷攻击
3月22日,Fantom 链上 Defi 项目 One Ring Finance 遭闪电贷攻击,项目方损失约146万美金。事件发生后 One Ring Finance 项目管理方暂停了漏洞合约,并计划对此次攻击受影响的用户提供补偿。
合约漏洞发生在 Oshare 合约在计算 share price 时,使用了对应的 pair 中的实时代币余额做为价格参数。由于 vault 合约的 deposit 和 withdraw 函数都会调用 getSharePrice 函数来进行价格计算,攻击者可以通过闪电贷向交易对中通过调用 deposit 函数注入大量的资金操纵 share price,导致在后续调用 withdraw 函数时得到的 share price 远高于 deposit 时的数值,形成价差以此获利。
CoboComment:
DeFi 项目在所有价格计算模型中,都应避免使用任何交易池的实时余额、比例等作为计算参数。因这类参数易遭受大资金的操纵。尤其是当使用实时余额时,更可能通过闪电贷进行操作,使用攻击者以较低的攻击成本发起价格操纵攻击。
Reference:
https://mp.weixin.qq.com/s/MyR_O8wuZJUT1S6eIMH9TA
https://medium.com/oneringfinance/onering-finance-exploit-post-mortem-after-oshare-hack-602a529db99b
PYESwap 攻击事件
3月24日,PeckSheild 发表 Twitter 称 bsc 链上 Defi 项目 PYESwap 遭到攻击,损失约260万美金。
PYESwap 采用了类似 Uniswap 的交换机制,利用恒定价格公式来计算交换的比值。与 Uniswap 不同,PYESwap 的 pair 合约在每次进行 swap 时并没有检查交换后的 K 值守恒问题,而是由 router 维护 K 值以保证兑换过程资金不会出现损失,并在 pair 合约中限制了只有 router 合约可以调用 swap 函数。
此次攻击前 PYE 项目方部署了新的 factory 和 router 合约,在 factory 合约中注释掉了部署 pair 合约中 swap 函数对调用者是否是 router 合约的校验,导致任何用户都可以调用没有 K 值检查的 swap 函数,使攻击者可以任意设置兑换的金额,从而盗取交易池中的资产。
事件发生后,有声音指责称此次攻击事件为 PYE 官方进行 Rug Pull。但 PYE 方则否认这一指控,称此次事件是开发者疏忽。
CoboComment:
3月23日1:30 PM,PYE 项目管理方部署了新的有漏洞的 Factory 和 Router 合约;3月24日 9:05 AM, PYE 项目方发布 Twitter 称此次部署为项目移植升级,号召用户将资产转移到新的 PYE 交易池中;3月24日 2:16 PM,本次攻击发生。连续操作的时间节点以及异常注释检验代码的操作,都加重了项目方面内部做恶的嫌疑。
投资者面对项目方突发进行的大规划流动性迁移和合约升级时务必保持警醒,避免资产损失。
Reference:
https://twitter.com/PeckShieldAlert/status/1507024110534422532
https://twitter.com/PyeEcosystem/status/1506799371874037765
Revest Finance 遭重入攻击
3月27日,以太坊主链上的 Defi 项目 Revest Finance 遭到重入攻击,项目损失约200万美金。
Revest Finance 采用将 ERC20 代币打包生成 ERC1155 NFT 代币的形式来进行资产管理和交易。用户可以自定义生成 NFT 数量以及每个 NFT 所包含的 ERC20 代币种类和数量,生成 NFT 后用户也可以对 NFT 对应的 ERC20 种类和数量进行修改。
本次攻击的漏洞点在于 ERC1155 的回调函数 onERC1155Received 发生了重入,由于每次生成NFT代币的 fnftsCreated 这一全局变量是在 NFT 代币生成后进行累加,所以攻击者可以通过重入攻击在 fnftsCreated 没有更新前修改之前的 NFT 代币所对应的 ERC20 代币种类和数量。
具体来说,以盗取 RENA 交易序列为例,攻击者首先生成了2个编号为1027的 NFT 代币,且没有向其中质押 ERC20 代币,而后攻击者再次生成3600个编号为 1028 的 NFT 代币,同样没有向其中质押 ERC20 代币。
在生成编号为 1028 代币的过程中发生了重入攻击,攻击者调用 depositAdditionalToFNFT 函数向编号为1027、数量为1 的 NFT 代币增加 1 个 RENA 代币的质押资产。此时由于 1027 代币数量为2,而攻击者只改变了其中一个 NFT 的质押信息,所以需要生成新的 NFT 代币以做区别。
因为生成的新的 NFT 代币的行为是在重入攻击中实施,所以代表新生成 NFT 编号的 fnftsCreated 没有更新(在本例中为1028),且在后续更新 NFT 信息的函数中没有检查对应的 NFT 信息是否已经存在,这就导致攻击者原本质押的 1 个代币的更新信息被更新到了所有之前生成的 3600 个编号为 1028 的 NFT 中,攻击者以此获利。
事件发生后, Revest Finance 采取了补救措施,包括更新漏洞合约,使用对每一个函数都进行重入攻击保护,并且会展开新一轮的安全审计工作。
CoboComment:
涉及到转账回调函数的代币实现都需要考虑重入攻击发生的可能。同时涉及到状态变化的操作也应该考虑在转账调用之前进行更新。比较保险的做法就是对所有函数都使用OpenZeppelin ReentrancyGuard进行保护。
Reference:
https://coinyuppie.com/erc1155s-reentrancy-attack-appears-again-a-brief-analysis-of-revest-finance-being-attacked/
https://coincodecap.com/revest-protocol-exploit-2-million-stolen
https://slowmist.medium.com/revest-finance-incident-analysis-6fcd9b6be207
Cobo Labs 希望协助加密世界投资者规避风险、提高收益,为传统金融机构、风险投资公司、通证基金、个人投资者、交易所、媒体等伙伴提供客观、有深度的数据分析。
关于亚太最大的加密货币托管及资管平台 Cobo:我们向机构提供领先的安全托管与企业资管业务;我们向全球高净值合格投资人提供加密数字钱包业务和丰富灵活的定期与结构化产品,我们关注金融创新,并于 2020 年第三季度成立了第一家面向全球机构的基金产品「DeFi Pro」。