被黑分析|ShapeShiftFOXColony授权信任链缺陷

admin 2026-05-16 04:29:08 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: ShapeShiftFOXColony项目在Arbitrum上的EtherRouterCreate3合约因元交易机制与DSAuth授权逻辑的语义冲突遭攻击。攻击者通过executeMetaTransaction的任意自调用功能,结合DSAuth对address(this)的自动授权绕过auth修饰符,将resolver替换为恶意版本,最终通过delegatecall清空合约持有的132,704.59USDC和1.9495WETH(约13.6万美元)。漏洞根因为元交易未过滤敏感函数选择器,且自调用时DSAuth无条件放行,导致完整权限绕过。 综合评分: 85 文章分类: 漏洞分析,区块链安全,智能合约安全,应急响应,威胁情报


cover_image

被黑分析 | ShapeShift FOX Colony 授权信任链缺陷

原创

慢雾安全团队 慢雾安全团队

慢雾科技

2026年5月14日 21:18 中国香港

在小说阅读器读本章

去阅读

背景

2026 年 5 月,ShapeShift FOX Colony 项目部署在 Arbitrum 上的 EtherRouterCreate3 合约遭到攻击。攻击者利用合约元交易机制中的「任意自调用」能力,配合 DSAuth 对 address(this) 的自动授权逻辑,绕过 auth 修饰符将合约的核心路由组件 resolver 替换为恶意版本,进而通过 delegatecall 清空合约持有的全部 ERC20 资产。本次攻击的本质是「元交易元语与内部自调用授权模式的语义冲突」所导致的一次完全权限绕过。

攻击概览

| | | | — | — | | 字段 | 详情 | | 攻击类型 | 访问控制绕过 / 元交易任意自调用致 Resolver 劫持 + 恶意 delegatecall 资产清空(Access Control Bypass via Meta-Transaction Self-Call → Resolver Hijacking) | | 受害合约 | 0x5c59d0ec51729e40c413903be6a4612f4e2452da(EtherRouterCreate3 / EtherRouter,ShapeShift FOX Colony) | | 攻击者 EOA | 0xeed236afb6967f74099a0a6bf078bc6b865fbf28 | | 攻击合约 | 0x835a701fd76b96a76ee84de037d41f059ee29f5c(临时) | | 获利金额 | 132,704.591501 USDC + 1.9495 WETH(约合 136,000 USD) | | 所在链 | Arbitrum | | 交易数量 | 单笔原子交易(攻击逻辑在 constructor 中全链路执行) |

漏洞根因

executeMetaTransaction 的任意自调用:address(this).call(callData) 未过滤敏感 selector**

### 合约 EtherRouter 本身是一个基于 resolver 的可升级代理架构:对于未知函数选择器,fallback() 调用 resolver.lookup(msg.sig) 找到实现地址后通过 delegatecall 执行。元交易功能(executeMetaTransaction)由旧 resolver 0x7490022b0e44aa65c030ac0d6728382a29458fc5 路由到实现合约 0x4e7f1e1e263678590007e89b7e129686ba7758d4 执行。该实现合约未开源,以下基于反编译结果:

function executeMetaTransaction(    address userAddress,    bytes memory functionSignature,    bytes32 sigR,    bytes32 sigS,    uint8 sigV) public returns (bytes memory) {    // 使用 nonce、address(this)、chainid、functionSignature 构造消息    // 通过 ecrecover 校验签名恢复地址 == userAddress    require(recoveredAddress == userAddress);
    // nonce++    _executeMetaTransaction[userAddress]++;    // 构造 calldata    bytes memory callData = abi.encodePacked(        functionSignature,        0x2bcc191e283bfba76a1369ec8ba06566f33010645097c104c312753e04935e8,        userAddress    );
    // ⚠️ 漏洞点:验签后对 address(this) 执行任意 functionSignature 自调用,    // 未禁止 setResolver(address)、setOwner(address)、setAuthority(address) 等敏感 selector    (bool success, bytes memory returnData) = address(this).call(callData);    require(success);
    emit MetaTransactionExecuted(userAddress, msg.sender,     functionSignature);        return returnData;}

**问题本质:executeMetaTransaction 的设计意图是允许用户通过签名执行某些非敏感操作,但它对 functionSignature 不做任何过滤。攻击者可以使用自己的有效签名,让合约对自身调用 setResolver(恶意地址)。

DSAuth.isAuthorized 的自动授权:src == address(this) 即放行

EtherRouter.setResolver(address) 受到 auth 修饰符保护,本应只允许 owner 或 authority 调用:**

Resolver public resolver;
function setResolver(address _resolver) public auth {    resolver = Resolver(_resolver);}

但 DSAuth.isAuthorized(address src, bytes4 sig) 中存在自调用自动授权逻辑:

function isAuthorized(address src, bytes4 sig) internal view returns (bool) {    if (src == address(this)) {        return true; // ⚠️ 漏洞点:自调用无条件授权    } else if (src == owner) {        return true;    } else if (authority == DSAuthority(0)) {        return false;    } else {        return authority.canCall(src, this, sig);    }}

**当 executeMetaTransaction 通过 address(this).call(setResolver(…)) 触发自调用时,setResolver 中看到的 msg.sender 即为合约自身 0x5c59…,因此被 DSAuth 自动放行。

单独来看,这两处设计都不算明显漏洞——自调用授权在许多代理模式中很常见,元交易机制本身也合理。但两套逻辑同时存在时,语义冲突就产生了:元交易提供的「任意自调用」能力恰好撞上了 DSAuth 的「自调用即信任」逻辑,合在一起就是完整的权限绕过链。

EtherRouter.fallback() 的 delegatecall 动态路由:Resolver 被劫持后的完整控制权移交**

fallback() external payable {    address target = resolver.lookup(msg.sig);    require(target != address(0));
    // ⚠️ 漏洞点:对 resolver 返回的地址无条件执行 delegatecall,    // 一旦 resolver 被替换,任意未知 selector 都会被路由到攻击者实现    assembly {        calldatacopy(0, 0, calldatasize())        let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)        returndatacopy(0, 0, returndatasize())
        switch result        case 0 { revert(0, returndatasize()) }        default { return(0, returndatasize()) }    }}

resolver 被替换后,攻击者只需调用 EtherRouter 上不存在的任意函数选择器,fallback() 就会无条件委托到攻击者控制的恶意实现。

**### 恶意 Resolver 与 Drain 实现:无权限的函数映射注册表 + address(this) 资产清空

攻击者预先部署了两个合约:

恶意 Resolver

0x4e321af09012e15a67756522187c05b108b7ee0a(未开源,反编译):**

contract FunctionPointerRegistry {    mapping(bytes4 => address) private _lookup;        function lookup(bytes4 sig) public returns (address) {        return _lookup[sig];    }        // ⚠️ 漏洞点:无任何权限控制,任何人可注册任意 selector → implementation 映射    function set(bytes4 functionSig, address implementation) public {        _lookup[functionSig] = implementation;    }}

**恶意 Drain 实现

0x0b971e0a8ecc7d5b2465c903cf75aeaedbfc39e2(未开源,反编译):**

function drain(address token, address recipient) public {    // ⚠️ 由于该函数由受害合约 delegatecall 执行,    // address(this) 实际为受害合约地址 0x5c59...    uint256 balance = IERC20(token).balanceOf(address(this));    IERC20(token).transfer(recipient, balance);}

攻击盈利公式

攻击者 EOA 签名 → executeMetaTransaction 自调用 setResolver(恶意 resolver)→ DSAuth 自调用绕过 → resolver 被劫持→ 调用 EtherRouter.drain(token, attacker)→ fallback() → 恶意 resolver.lookup(0x837971e4) → 恶意 drain 实现→ delegatecall → drain 中 address(this) == 受害合约→ IERC20(token).balanceOf(受害合约) → IERC20(token).transfer(attacker, balance)= 攻击者获得受害合约持有的全部 ERC20

**## 攻击流程

攻击过程仅在一笔交易中完成,所有逻辑在临时攻击合约 0x835a701fd76b96a76ee84de037d41f059ee29f5c 的 constructor 中执行。**

**### 第一阶段:部署恶意基础设施

  1. 攻击者 EOA 0xeed236afb6967f74099a0a6bf078bc6b865fbf28 发起交易,创建临时攻击合约 0x835a701fd76b96a76ee84de037d41f059ee29f5c。
  2. 攻击合约调用恶意 resolver 0x4e321af09012e15a67756522187c05b108b7ee0a 的 set(bytes4,address),将 drain(address,address) 的选择器 0x837971e4 映射到恶意 drain 实现 0x0b971e0a8ecc7d5b2465c903cf75aeaedbfc39e2。

第二阶段:通过元交易自调用劫持 Resolver

  1. 攻击合约调用受害合约 0x5c59d0ec51729e40c413903be6a4612f4e2452da 的 executeMetaTransaction()。由于该函数不在 EtherRouter 自身 ABI 中,调用进入 fallback(),由旧 resolver 路由到元交易实现 0x4e7f1e…。
  2. executeMetaTransaction 通过 ecrecover 校验签名,恢复出攻击者 EOA,签名验证通过(攻击者使用的是自己的有效签名,非签名伪造)。
  3. executeMetaTransaction 构造自调用 calldata setResolver(0x4e321af…) 并执行 address(this).call(callData)。此时上下文是受害合约,所以 msg.sender == 0x5c59…。DSAuth.isAuthorized() 因 src == address(this) 返回 true,resolver 被成功替换。

第三阶段:通过被劫持的 Resolver 清空资产

  1. 攻击合约调用受害合约的 drain(USDC, 0xeed236…)。该函数不在 EtherRouter 原生 ABI 中,进入 fallback()。被劫持的 resolver 返回恶意 drain 实现 0x0b971e0…,受害合约对其 delegatecall。恶意代码查询 USDC.balanceOf(0x5c59…) 得到 132704591501(即 132,704.591501 USDC),随后调用 USDC.transfer() 直接转入攻击者 EOA。
  2. 攻击合约再次调用 drain(0xf929…, 0x835a701f…),依相同路径将被盗中间代币 841086343608217839604694 单位转入攻击合约。
  3. 攻击合约通过 Router 0x4752ba5dbc23f44d87826276bf6fd6b1c372ad24 将被盗中间代币在 Pair 0x5f6ce0ca… 中 swap 为 1.949506469643782660 WETH,WETH 直接转入攻击者 EOA。**

**### 获利闭合

| | | | | — | — | — | | 资产 | 金额 | 流向 | | USDC | 132,704.591501 | 受害合约 → 攻击者 EOA | | WETH | 1.9495 | 中间代币 swap → 攻击者 EOA |

资金追踪

**通过慢雾 MistTrack 对攻击者 EOA 0xeed236afb6967f74099a0a6bf078bc6b865fbf28 进行地址画像与交易对手分析:

  • Gas 来源:攻击者的初始 Gas 由 TornadoCash 提供(地址 0x12d66f87a04a9e220743712ce6d9bb1b5616b8fc )。

  • 恶意标签:MistTrack 已标记该地址为 ShapeShift Exploiter

  • 主要痕迹:

  • Relay.link — $4,368.08,DEX 聚合器,用于资产兑换。

  • Tornado.Cash — $218.09,从混币器提取初始 Gas。

  • LI.FI — $137,073.66,跨链/DEX 聚合器。

攻击者盗取的资金流入了Spark.fi Saving,且存在 Tornado.Cash 交互记录,增加了后续追踪的难度。慢雾 MistTrack 将持续监控相关地址的资金动向。**

总结

这次攻击的核心教训是:当合约同时具备「元交易任意自调用」和「自调用自动授权」两套语义时,二者会构成一个完整的权限绕过链——这不是单点代码漏洞,而是跨组件语义冲突的必然结果。 合约开发者在设计元交易或 relay 机制时必须明确划分敏感函数边界,至少在 executeMetaTransaction 中维护一份禁止调用的 selector 列表,并慎用 src == address(this) 的无条件自调用授权。慢雾安全团队建议项目方在部署前进行完整的外部安全审计。**

往期回顾

Shai-Hulud 恶意软件深度剖析:开源即失控 ?

MistEye 安全前置闸门正式发布,筑牢 AI Agent 前置检测防线

威胁情报|仿冒 TronLink 的 Chrome 扩展钓鱼攻击分析

慢雾|RWA 智能合约安全审计服务正式推出

Grok 被利用背后:AI Agent 权限链滥用分析

慢雾导航

慢雾科技官网

https://www.slowmist.com/

慢雾区官网

https://slowmist.io/

慢雾 GitHub

https://github.com/slowmist

Telegram

https://t.me/slowmistteam

Twitter

https://twitter.com/@slowmist_team

Medium

https://medium.com/@slowmist

知识星球

https://t.zsxq.com/Q3zNvvF


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:慢雾科技 慢雾安全团队 慢雾安全团队《被黑分析 | ShapeShift FOX Colony 授权信任链缺陷》

评论:0   参与:  0