三公自动算账 攻击者先部署了一个无价值的假代币(0xd9b5)

这是 ACai_sec(和之前 Balancer 那篇同一作者)分析的一起智能合约攻击事件。核心一句话:

Ether.fi 的 AtomicQueue 合约因为「订单校验逻辑实际没实现」,被攻击者借着一个根本不存在

的函数调用,盗用了受害者早已给出的代币授权,转走约 14.44 枚 liquidETH(价值约 38k 美元)

[citation:web:20.1]。

一、攻击链路(Trace 还原,就三步)

攻击者先部署了一个无价值的假代币(0xd9b5);

调用 AtomicQueue.updateAtomicRequest() 设置订单——内容是「用假代币换取受害者 0x1226 地址的 liquidETH」;

调用 AtomicQueue.solve() 完成订单;

反复执行 2–3 步,持续获利[citation:web:20.1]。

二、漏洞机制:一次「静默成功」的假校验


这是全文最值钱的技术点。AtomicQueue 的 solve() 流程里,本该有一道校验——调用 solver 的

 finishSolve() 函数,确认这笔交易「符合 solver 的要求」,通过后才继续兑换。


问题出在:受害者地址 0x1226 根本不是专门为 AtomicQueue 服务的 solver 合约,而是一个通用

的 CoinbaseSmartWallet 合约——它压根没有实现 finishSolve() 这个函数[citation:web:20.1]。


于是发生了一个经典的 Solidity 陷阱:

AtomicQueue 对 CoinbaseSmartWallet.finishSolve() 的调用,因为目标合约没有这个函数,回退到了

 fallback 函数;而 fallback 里没有写任何处理逻辑,这个调用静默成功(不 revert)。


于是「solver 同意」的假象被制造出来了,AtomicQueue 误以为校验通过,接着调用 transferFrom 把

受害者的 liquidETH 转给了攻击者[citation:web:20.1]。


根因拆成两层:

表面:solve() 缺乏访问控制,任何人能发起订单(PANews/SlowMist 的口径也指向这一点)[citation:web:20.3];

深层:校验逻辑「依赖外部调用不 revert 即视为同意」,却被「目标合约没实现该函数 → fallback 静默成功」绕过。

三、为什么攻击能落地:两个前提

假代币:攻击者用自己铸造的、零价值的代币作为「支付方」,订单方向天然对自己有利;

历史授权:受害者 CoinbaseSmartWallet 早在 2024-07-05 和 2025-07-14 就向 AtomicQueue 合约授权过

 liquidETH。攻击者不需要新拿授权,只是「借 AtomicQueue 的 transferFrom 权限」,把这份早已存在的

授权套现了[citation:web:20.1]。


这第二点尤其关键——很多授权型漏洞,攻击者利用的不是新漏洞,而是用户(或合约)之前随手给出、又忘

了撤销的授权。

四、能带走的三条安全教训

别把「外部调用没 revert」当成「校验通过」。Solidity 里调用不存在的函数会静默落到 fallback,而 fallback

 默认是空实现。凡是「调用对方某个函数来确认对方同意」的模式,都必须显式校验:要么要求目标合约真的实

现了该函数(extcodesize / 接口检查),要么用返回值和状态变量来确认,而不是只看「有没有 revert」。

「谁都能写订单」+「订单里指定任意 solver」是危险组合。updateAtomicRequest() 允许任意地址设置订单、

并指定 solver,等于把「让谁付出代价」的控制权交到了攻击者手里。这类撮合/求解器合约,solver 的准入和

订单的可信来源必须有强约束。

授权要「最小化 + 及时撤销」。受害者早在两年前就给 AtomicQueue 授权了,攻击只是引爆了这颗陈年炸弹。

合约和 EOA 一样,只给真正需要的额度授权,用完就 revoke——作者也提醒:在没有实现检测逻辑前,不要向 

AtomicQueue 授权任何代币[citation:web:20.1]。


---


一句话总结:这不是一个「没写校验」的低级漏洞,而是一个「写了校验、但校验的调用被 fallback 静默吞掉了」

的隐蔽漏洞——攻击者没有突破任何一行 revert,只是让一个「看起来会拦一下」的函数调用,变成了一次无声的

放行。这种「静默成功」的假校验,比直接没写校验更难发现,也更值得警惕。


如果你在写或审计 Solidity 合约,我可以帮你把这个漏洞模式整理成一个可复用的检查清单(外部调用校验、fallback 

兜底、授权最小化、solve/撮合函数的访问控制),或者展开讲 Solidity 里「如何正确做函数存在性检查」(extcodesize、

try/catch、EIP-165 接口检测的取舍)。


0 评论

发表评论