KKDEMIAN

EIP-7702 攻击链复盘:18 小时准备,一条签名,一个机器人

链上记录显示这是一次提前近 18 小时准备、经过三次演练的定向行动:02:28 部署测试合约,13:51 与 16:20 在自有钱包上彩排委托与扫荡,15:59 部署最终合约,20:20 才对目标发起真正的授权。EIP-7702 没有制造漏洞,它只是把「一次签名」的后果从「转走一笔钱」放大成「接管一个地址的全部能力,并且长期有效」—— 事后那个机器人又扫了 3.5 小时。

思考

更新(10-30 02:23 UTC):币安在《Security Incident Update》中称已撤销受影响地址的授权,并把根因指向被攻陷的 DevOps 笔记本与服务容器 —— 与本文第七节根因矩阵里「签名基础设施被侵害」这一行的方向一致。但撤销交易的哈希仍未公布,链上尚无法独立复核,所以第七节「后门关了吗」的判断仍按公告前的状态保留。公告拆解见币安给出根因。

本文基于公开链上数据与第三方分析。币安尚未公布官方 post-mortem,根因未经确认。数据截至 2026-10-30 00:30 UTC。

TL;DR

签名即部署,部署即持久,执行即身份。但这次真正的技术含量不在合约,在工程封装。

  • 不是临时起意。 准备期近 18 小时:02:28 部署测试合约 → 13:51 与 16:20 在三个自有钱包上彩排委托与扫荡 → 15:59 部署最终合约 → 20:20 才动手。中间留了 4.3 小时的观察窗口。
  • 不是同一笔交易。 授权(Type-4,20:20:59)与清空(普通交易,20:24:23)隔了 17 个区块 / 3 分 24 秒 —— 而 Type-4 交易在 mempool 里是公开可见的。那 3 分 24 秒本来是可以拦截的窗口。
  • 50 条授权是 nonce 降序,恰好只有 1 条生效。 降序是刻意的:升序会让命中后每条更高 nonce 依次生效,把账户 nonce 连推 15 次。
  • 不是「63 种代币」。 calldata 解出来是 65 个数组元素:1 个 address(0)(ETH 占位符)+ 64 个 ERC-20。
  • 委托持久性有直接证据:事后 operator 又发起 12 次 sweep,其中 4 次是 23,100 gas 的空轮询(0 笔转账)—— 一个机器人在反复试探有没有新入账。
  • 成本荒谬:主扫荡手续费 0.000414 ETH ≈ $0.91,搬走约 25 亿美元,比例约 1 : 27 亿。

一、准备期:18 小时、三个测试钱包、一次彩排

把 operator 地址(0x7c8601d4…6b5ca0)的交易按时间排开,准备节奏非常清晰:

UTC(10-29) 动作 细节
02:28:59 部署测试合约 首笔合约创建,gas 324,710
13:51:35 / 13:51:59 两个测试 EOA 的 7702 委托 0x837810E3…、0x9C29BA2D…
14:19:59 / 14:24:11 对上述地址执行测试扫荡 gas 112,046 / 77,846
15:59:11 部署最终恶意合约 0x63e842… gas 415,057
16:20:47 / 16:25:59 第三个测试 EOA 委托到最终合约 两次授权,可能在测试 nonce 处理
16:30:11 / 16:47:23 对第三个 EOA 执行彩排扫荡 验证合约逻辑
20:20:59 对 Binance 14 发起真实授权 50 条授权,1 条生效
20:24:23 主扫荡 约 25 亿美元

这改变了对攻击者的判断。 他不是「拿到私钥后随手一转」,而是先在自己控制的账户上把完整链路跑通,再对目标执行。

恶意合约 15:59 部署,彩排 16:47 完成,真正动手在 20:20 —— 中间空了 3.5 小时。这说明攻击者在等待合适的执行时机:可能是等热钱包余额达到峰值,也可能是等某个签名窗口出现。

二、链上复核:授权与执行是分离的两笔交易

项目 授权交易 清空交易
时间(UTC) 20:20:59 20:24:23
区块 26,300,753 26,300,770
类型 Type 0x4(SetCode) Type 0x2(普通 EIP-1559)
From 0x7c8601d4…(operator) 同一 operator
To Binance 14(0x28c6…1d60) 同一地址
Input 0x(空) 0x8a179be4…(sweep)
Gas used 1,258,562 2,455,349
手续费 0.006545 ETH(≈$14.5) 0.0004138 ETH(≈$0.91)
作用 把 EOA 代码写成 0xef0100‖0x63e842… 以 EOA 身份执行批量转账

两个细节值得单独指出。

第一,授权交易的 input 是空的。 真正的内容在 Type-4 交易特有的 authorization_list 字段里 —— 常规的「看 calldata」监控完全看不到它。

第二,清空交易是一笔再普通不过的 EOA 调用。 任何地址都可以发;它能成功,只因为目标地址的代码已经被换成了攻击者的实现,而实现里硬编码了「只允许 operator 调用」。

这两笔交易之间隔了 3 分 24 秒,而 Type-4 交易在 mempool 里公开可见。 如果监控系统对「交易所地址发起 SetCode 交易」设了告警,这段时间足够暂停该钱包的签名权限。

没拦住,说明行业监控仍以「余额流出」为核心指标,而不是「代码被改写」。

三、Nonce 降序:50 条为什么恰好只有 1 条生效

这是整条攻击链里最精巧的一处,链上数据把它验证得很干净:

  • 50 条授权的 nonce 从 18,914,824 递减到 18,914,775,全部以 Binance 14 为 authority、指向同一合约、chain_id = 1
  • 只有 18,914,809 生效,其余 49 条 均为 invalid_nonce
  • 生效后账户 nonce 变为 18,914,810,下方 34 条因「过低」全部失效

降序排列是关键。

规则是「元组 nonce 必须等于账户当前 nonce 才生效,否则跳过而不回滚」。所以:

  1. 处理 824 → 810 这 15 条时,链上 nonce 只有 809,全部「过高」被跳过
  2. 处理到 809 时命中,代码写入,nonce 变为 810
  3. 剩下的 808 → 775 共 34 条变成「过低」,全部跳过

如果按升序提交,命中 809 之后,810、811……824 会依次生效,nonce 被连续推高 15 次 —— 热钱包自己的交易队列会瞬间错位。降序保证了「最多一条生效」。

gas 消耗 1,258,562,而这个数字可以精确对上:

50 × 25,000  = 1,250,000   每条元组按 PER_EMPTY_ACCOUNT_COST 预收
− 12,500                   唯一有效元组命中已存在账户,退 PER_AUTH_BASE_COST 的差额
+ 21,000                   交易内在 gas
+ 62                       calldata 等
= 1,258,562

一分不差。 规范对授权列表按 PER_EMPTY_ACCOUNT_COST(25,000)× 条数预收,只对 authority 非空的有效元组退 12,500。所以 49 条诱饵不是免费的 —— 每条实打实烧掉 25,000 gas,发送者为真假元组一并付费。

50 条覆盖的是「签名到上链」的时间差

窗口顶部比实际 nonce 高 15 笔。对高频热钱包来说,这大约是几十秒到一分多钟的漂移量。

这提供了一个关于根因的线索:如果攻击者手里有私钥、又能直连节点读 nonce,一条就够。需要一次签 50 条,通常意味着签名侧看不到实时链上状态 —— 要么是批量预签,要么是通过某个只负责签、不负责读的接口拿到的授权。

这更接近「签名基础设施被利用」,而不是「私钥被复制后直接操作」。

签名对象不是 EIP-712 —— 所以硬件钱包渲染不出来

7702 授权的签名对象是:

keccak256(0x05 ‖ rlp([chain_id, address, nonce]))

这不是 EIP-712 结构化数据。 意味着硬件钱包和多数签名界面无法把「你正在把账户代码委托给 0x63e8…」渲染成可读内容 —— 用户看到的很可能只是一串哈希。

这种「语义不可见」是 7702 从设计上就带来的盲签风险,不是某个钱包厂商的实现疏忽。

四、执行层:一笔调用扫走 65 个地址

恶意合约未验证源码,但从 calldata 可以还原接口:sweep(address recipient, address[] tokens),选择器 0x8a179be4。

  • arg0 = 主接收地址(当前以太坊持仓约 21.7 亿美元)
  • arg1 = 65 个唯一地址,第一个是 0x0000…0000,其余 64 个是 ERC-20

所以准确表述是:1 个 ETH 占位符 + 64 个代币,不是「63 种代币」。 公开分析里的「63」更可能是实际转账成功的数量 —— 差额来自零余额、转账被拒或重复资产。

三个设计细节:

  1. 硬编码 caller 校验 —— 只有 operator 能触发
  2. address(0) 作为 ETH 占位符 —— 同一个数组同时处理原生币和代币
  3. 逐项容错 —— 单个代币失败不回滚整笔交易,这才让它能一次打包这么多资产

为什么不需要任何授权? 因为委托代码运行在 Binance 14 的上下文里:对每个代币合约而言,msg.sender 就是热钱包本身,balanceOf(address(this)) 读到的就是热钱包余额。

它不是在「调用别人的钱」,它自己就是持有人。 这是 7702 与传统 drainer(需要骗取 ERC-20 approve)最本质的区别。

五、持久性的直接证据:12 次扫荡与空轮询

授权生效后,operator 在 3.5 小时内又发起了 12 次 sweep 调用:

时间(UTC) Gas used 解读
20:24:23 2,455,349 主扫荡,65 个地址
20:41:23 100,738 小额补扫
20:59:47 83,626 小额补扫
21:04:23 806,166 中等批次
21:44:11 732,036 中等批次
22:39:35 4,578,329 大额新入账被扫
23:36:47 / 23:37:23 / 23:37:47 / 23:38:23 23,100 ×4 空轮询,0 笔代币转账
23:54:59 23,100 空轮询
23:56:47 31,900 小额扫荡后停止

23,100 gas 的调用已被验证为 0 笔代币转账 —— 21,000 的基础交易成本加 2,100 的额外开销。

这就是一个机器人每隔几十秒到几分钟调用一次 sweep:有余额就转走,没有就白花 2,100 gas。

这是「持久委托 = 自动收款机」最直接的链上证据,也彻底否定了「临时执行」的说法。

一个有意思的细节:Binance 14 目前仍留有约 4,790 万美元资产。原因很可能是攻击者的代币清单是离线枚举的固定列表(65 个地址),而不是链上全量扫描 —— 长尾代币和后来新入账的资产没被覆盖。这也解释了 22:39 那次 458 万 gas 的大扫:有新资产进入了清单范围。

六、一个被忽略的边界:chain_id = 1

50 条授权的 chain_id 全部是 1。

按 EIP-7702,只有 chain_id = 0 的授权才能在所有支持该 EIP 的 EVM 链上重放。这里没有用。 因此:

  • 这条授权只能影响以太坊主网的 Binance 14
  • 比特币、Tron、Solana 根本没有 EIP-7702 这个机制 —— 那些链上的资金流出不可能来自同一条授权
  • 所谓「至少 9 条链、56–62 亿美元」的口径,必然混合了不同性质的动作:其他热钱包的独立失守、币安自己的归集或防御性转移、用户恐慌提现,或分析师的误标

这不是说多链损失不存在,而是说归因需要分开做。 以太坊上的 25 亿有完整的授权—执行因果链;其他链上的数字目前更多是余额变动,缺少同等级的因果证据。

把它统一记在「一次 7702 攻击」名下,会高估这次攻击的技术半径,也会误导后续的防御重点。

七、后门关了吗

截至可核验的最后一个时间点,委托仍然存在:

  • 10-30 00:10:35 UTC 的一笔转入交易中,Binance 14 的 to 对象仍带 proxy_type: eip7702 与实现地址
  • Binance 14 最近 50 笔转出中没有 Type-4 撤销交易(撤销需要签署一条指向 address(0) 的授权)
  • 攻击者的最后一次扫荡停在 23:56:47,之后 operator 只剩约 2,591 美元余额

两种可能:一是币安已通过其他方式(更换签名密钥、迁移地址)让委托失效,但公开数据没有撤销记录;二是委托仍在,只是攻击者暂时停手。

无论哪种,结论一样:7702 的撤销不是「停机」或「改密码」,而必须再签一条链上授权。 如果私钥已经泄露,撤销也只是临时的 —— 攻击者可以再次委托。

一个反向线索值得注意:如果攻击者完整持有私钥,币安签署撤销后他完全可以再次委托,形成拉锯。目前没有观察到这种拉锯 —— 这更倾向于「攻击者通过某个已被关闭的通道获得了签名能力」,而不是「长期持有私钥」。

根因矩阵因此需要更新:

假设 证据 评价
私钥直接泄露 50 条签名均有效;operator 有 Tornado 出资 仍可能,但无法解释为何要 50 条 nonce,以及为何停手后未再委托
签名基础设施被控 批量预签特征明显;测试钱包彩排;对 Hot Wallet 34 的 owner 关系有精准利用 当前解释力最强,但仍需 HSM/MPC 日志证实
内部人 / 供应链 18 小时准备、64 个代币的定制清单、知道热钱包的权限拓扑 不能排除,且与「签名接口被利用」可以并存

八、与合约漏洞的本质区别

维度 传统合约漏洞 7702 委托滥用
失效对象 合约逻辑 签名密钥与签名流程
触发方式 调用存在缺陷的函数 一条合法签名的授权元组
是否需要授权 通常依赖已有 allowance 不需要,地址自身即持有人
影响范围 单一协议资金 该地址名下全部资产
修复方式 暂停、补丁、治理 必须再签一条链上授权才能撤销
事后可逆性 可暂停协议 已转出的原生资产不可逆

7702 把「账户安全」从每笔交易的授权边界问题,变成了一次签名的代码托管问题。

而热钱包为了支持高频提现必须保持在线签名能力 —— 这恰好与 7702 的最坏情形正面相撞。

九、防守启示

对交易所与托管方,按优先级:

  1. 策略层拒绝 —— 热钱包地址禁止发起 Type-4 交易,除非白名单委托目标加多签审批。这是唯一能从根本上消除该路径的措施。
  2. 签名可读性 —— 硬件钱包与 MPC 必须展示「将代码委托给 0x…」。由于签名对象不是 EIP-712,这需要钱包厂商专门实现,不会自动获得。
  3. 监控对象换掉 —— 从「大额转出」改为「0xef0100 代码变更 + mempool 中的 Type-4 交易 + nonce 异常跳变」。要读的是实际存储的 23 字节 0xef0100‖address —— 按规范 EXTCODESIZE 返回 23,且 EXTCODEHASH 等外部读取操作不跟随委托,作用在委托指示符本身,所以能直接把委托目标解出来。
  4. 降低单点敞口 —— 热钱包只留运营浮动余额,超额自动归集;用「限额 allowance + 扫块合约」代替 EOA 直接持币。
  5. 权限隔离 —— 智能钱包的 owner 不要复用热钱包 EOA。本次攻击正是通过 Binance 14 对它名下的智能钱包发起调用,又拉走了约 7.8–8.23 亿 USDC。
  6. 应急 —— 签署指向 address(0) 的元组可清除委托,但私钥已泄露时攻击者可再次委托,必须同步轮换密钥并迁移地址。清除委托只是争取时间,不是修复。

对协议方:停止用 extcodesize、tx.origin == msg.sender 判断调用者身份 —— 7702 之后这些假设不再成立。

十、结论

这次攻击的真正结构是「18 小时准备 + 一条签名 + 一个机器人」:准备期用来验证合约与 nonce 策略,签名把热钱包变成攻击者可编程的账户,机器人在之后 3.5 小时里反复收割。

EIP-7702 没有制造漏洞。 它只是把「一次签名」的后果,从「转走一笔钱」放大成「接管一个地址的全部能力,并且长期有效」。

链上证据还修正了两个常见误解:委托不是「临时」的,它会一直存在到被显式清除;被扫走的也不是「63 个代币」,而是 64 个代币加原生 ETH,装在一个 65 元素的数组里。

对行业的启示不在合约层,而在签名语义层:只要签名系统无法区分「转账」和「委托代码」,无法把 0xef0100 的目标地址展示给审批人,无法在 mempool 阶段对 Type-4 交易告警,那么每一台在线签名的热钱包都是潜在的 Binance 14。

底线判断。 判断一个平台是否真正修复,不看它发了多少声明,而看三件事:链上是否出现指向 address(0) 的撤销授权、热钱包地址是否更换、签名策略是否开始拒绝 Type-4。 三者缺一,后门就只是暂时没人推。

参考资料


配套阅读:币安热钱包失守:一条合法签名,8 分钟,56 亿美元、EIP-7702 的签名流程、币安还没公开那份签名日志。gas 成本按 ETH ≈ $2,209 折算。本文基于公开链上数据与第三方分析,币安未发布官方 post-mortem,根因未经确认。DYOR。

相关主题:⛓️ L1 / L2
订阅更新

在 Telegram 或 X 关注每周研究、市场信号与上币动态。

更多文章: 思考查看全部
币安还没公开那份签名日志 —— 截至 10-30 凌晨的披露核对

六条公开表态,零条技术细节。币安至今没有官方确认攻击向量是 EIP-7702,没有发布签名请求记录、HSM/MPC 审计轨迹、策略引擎放行日志或第三方取证报告,也没有面向用户的正式事件公告。更值得注意的是口径:独立核算的外流 56.43 亿减去已冻结 26.2 亿约为 30 亿,而 CZ 认可的损失量级是 10 亿左右 —— 差三倍,说明「损失」从未被定义。

2026年10月30日
币安给出根因:被攻破的不是 EIP-7702,是一个有签名能力的服务身份

10-30 02:23 UTC 的《Security Incident Update》第一次给出根因口径:一名 DevOps 工程师的笔记本被攻陷,攻击者由此进入服务容器并提交未授权提现;币安称未发现私钥泄露证据,已撤销受影响地址的授权。总影响估算 63 亿、已冻结 30 亿、净敞口约 33 亿。这把事件从「协议漏洞」拉回「运维终端 → 服务凭证 → 签名能力」,7702 不是根因,而是让一笔受限额约束的提现变成一次不受限额约束的代码执行。

2026年10月30日
币安热钱包失守:一条合法签名,8 分钟,56 亿美元

攻击者在 15:59 部署好恶意委托合约,20:24 用一条由热钱包私钥签署的 EIP-7702 授权完成清空,20:32 才被分析师察觉,21:01 起发行方开始冻结。真正被抢走的时间窗口只有几分钟,而能挽回损失的手段 —— 稳定币黑名单 —— 只覆盖约 45%,原生 BTC/ETH 仍在攻击者手中。这不是合约被黑,合约没有漏洞;被攻破的是「谁有权让钱包执行代码」。

2026年10月30日