本文分析了多个利用智能合约标准(如ERC777、ERC20 Permit、ERC1155、EIP-2535等)漏洞进行攻击的案例,强调即使是社区认可的标准也可能存在风险。攻击手段包括利用callback检查缺失、输入验证不足、扩展调用问题、代理合约变量存储错误、以及approve/transferFrom中的竞争条件等,并建议采取多层次验证措施,如单元测试、模糊测试和模拟攻击,以降低漏洞风险。

本节包含的攻击在本质上与我之前讨论过的攻击类似,但我决定单独强调这些例子,以表明即使信任社区批准的标准,也不应放松警惕。看似值得信赖和可靠的东西可能存在弱点或带有风险的意外用例。
以下是一些攻击者利用常见“标准”遗漏的例子——我们并没有立即预料到陷阱:
- Lendf.Me / Uniswap imBTC-漏洞利用 (2020): 问题在于,当使用 ERC777 + ERC1820 标准时,用户有机会为 transferFrom() 函数创建自己的 tokensToSend() Hook。 黑客注册了自己的Hook合约,该合约在每次 imBTC 转移时都会调用 _callExchange 函数,这导致了相同代币的多次交换。 结果,他能够从 Uniswap 池中提取约 1728 ETH,并且在 Lendf.Me 中,他增加了抵押品并借入了价值约 2500 万美元的代币。 阅读更多:uniswap-lendf-me-hacks-root-cause-and-loss-analysis
- EIP-2612 Permit 重放 DAI (2022): 该漏洞利用基于 ERC-20 Permit 标准 (EIP-2612),该标准允许通过签名发行注销代币的权利,而无需单独的 approve。 在 anySwapOutUnderlyingWithPermit() 函数中,Multichain 没有检查作为代币传递的合约是否实际支持 permit(),并为 WETH 调用了它,其中失败的调用落入了 fallback.deposit() 而不是 revert。 благодаря этому и бесконечному approve в интерфейсе злоумышленник вывел из кошельков пользователей 308 ETH (~950 000 USD) без какой либо валидной подписи. 由于这个和接口中的无限 approve,攻击者在没有任何有效签名的情况下从用户的钱包中提取了 308 ETH(约 950,000 美元)。 损失估计约为 308 ETH(约 950,000 美元)。 阅读更多:without-permit-multichains-exploit-explained
- Revest Finance (2022): 由于 Revest Finance TokenVault 合约中缺少对 onERC1155Received 回调的可靠检查,ERC-1155 标准存在漏洞。 攻击者在 ERC-1155 Hook函数中使用“陷阱”来重新进入 depositAdditionalToFNFT 方法,人为地增加存储的存款,然后提取其他人的资产。 结果,价值约 2,000,000 美元的代币从协议中被盗。 阅读更多:revest-finance-vulnerabilities-more-than-re-entrancy
- Nomad Bridge (2023): 在这种情况下,问题是由于代理合约的易受攻击的实现而引起的。 在升级期间,使用 Merkle 树的根值 0x00 编写了 initialize 函数,该值被认为是有效的。 这导致任何人都可以使用假消息调用 process() 方法,并通过对已处理消息的验证。 因此,攻击者提取了被阻止在那里的资产,总成本为 1.9 亿美元。 阅读更多:https://medium.com/immunefi/hack-analysis-nomad-bridge-august-2022-5aa63d53814a
- Li.Fi (2023): 这里使用了 EIP-2535 模块化合约标准。 问题的根源在于受害者合约上的 depositToGasZipERC20 接受 _swapData 参数,该参数立即传递给 LibSwap.swap,而无需任何验证。 黑客只是更改了 _swap.callTo 和 _swap.callData 字段,插入了 transferFrom() 调用,从而从平台上提取了价值约 800 万美元的代币。 阅读更多:https://blog.solidityscan.com/li-fi-hack-analysis-521388128d22
- Tsuru ERC-1155 Hook漏洞利用 (2024): 在这种情况下,漏洞存在于 ERC-1155 标准中,即 TSURUWrapper 合约的 onERC1155Received 函数中:由于 require if replacement,缺少访问控制,任何人都可以调用 safeMint,铸造 1.672 亿 TSURU。 然后,攻击者通过 Uniswap 列出了被盗代币,价格约为 137.78 ETH,当时价值约 410,000 美元。 该事件表明,即使对条件语句进行微小的更改,如果没有强大的授权,也可能非常危险。 阅读更多:Tsuru-Hack-Analysis
- Pike Finance (2024): 在 Pike Beta 协议中,当由于添加了新变量而导致 initialzed 标志槽移动并且合约再次被视为未初始化时,违反了根据“initializer 代替 constructor”标准(可升级代理)的代理合约的安全性。 攻击者利用了这一点,调用了 initialize 函数,将自己添加到活动管理员列表中,然后通过 upgradeToAndCall 将逻辑更新为恶意逻辑,并提取了 99,970.48 ARB、64,126 OP 和 479.39 ETH(总计超过 160 万美元)。 阅读更多:decoding-pike-finance-exploit-quillaudits
- ERC-20 approve 抢跑交易竞争条件(多个案例,2018–2023): 由于 ERC-20 标准不要求首先重置 allowance,攻击者经常拦截 allowance 更改交易,并快速连续进行两次转账,提取超出预期的资金。 估计各种代币的总损失达数千万美元。
因此,即使是最常见和“经过验证”的标准也可能隐藏着意想不到的风险:从错过的回调检查到不正确的输入验证和代理槽位移位。 基于这些“标准”遗漏的攻击不需要奇异的技术——有时一行未受保护的代码就足以窃取数百万美元。 这里最重要的是不要忽略审计中对某些标准的提及,因为有时会存在这种诱惑,因为所有这些都已经使用了不止一次,但正如你所知,细节决定成败。
如果谈论 конкретных точках, то стоит обратить внимание на: 具体要点,那么值得关注的是:
- 回调检查 (onERC1155Received, onERC721Received 等):确保接收者地址是可靠的,并排除Hook函数中的“陷阱”。
- 输入数据和参数验证(代币地址、数组大小、calldata 长度):所有外部参数在使用前都应通过 require 进行检查。
- 扩展调用的支持和正确性(ERC-20 permit、ERC-777 Hook):检查被调用的合约是否实际实现了预期的接口,并且在 fallback 函数中没有崩溃。
- 代理中的变量存储和偏移(可升级代理):在逻辑或变量添加中的任何更改之后,确保 initialzed 和其他标志位于正确的槽中。
- approve/transferFrom 中的竞争条件:避免“非零”allowance,使用类型安全的 increaseAllowance/decreaseAllowance 模式。
- 模块化标准:callTo、callData 和访问检查应受到严格限制和验证。
为了最大限度地降低所述错误的风险,测试应建立在“多层验证”的原则之上:首先,为所有边缘情况编写单元测试,然后添加基于属性的测试和模糊测试 (Echidna, Foundry-fuzz) 来生成随机组合并验证基本不变性。 值得在测试链上运行 сценарии,并通过带检测的调试器 (Tenderly) 模拟攻击,确保没有意外的状态改变会隐藏在乍一看似乎正确的接口后面。