ITPub博客

首页 > IT基础架构 > 网络安全 > 安全审计报告:重入与访问控制审查:Arbitrum Bridge

安全审计报告:重入与访问控制审查:Arbitrum Bridge

网络安全 作者:ITPUB社群 时间:1970-01-01 08:33:46 0 删除 编辑

安全审计报告

重入与访问控制审查 – Arbitrum Bridge 日期:2026年10月12日 编制方:[Your Company] – 高级 DeFi 安全研究与审计团队

1. 执行摘要

Arbitrum Bridge 是在以太坊 L1 与 Arbitrum roll‑up(L2)之间转移资产的主要网关。其 TVL 约为 $3.64 B,是攻击者的高价值目标。本次审计聚焦于两个关键安全维度:

| 范围 | 描述 |
| --- | --- |
| 重入 | 检查桥的存款、取款和挑战合约中的所有外部调用、回调以及状态更新顺序。 |
| 访问控制 | 审查基于角色的权限、仅管理员函数、可升级机制以及跨链消息认证。 |

关键发现

| # | 类别 | 严重性(1‑10) | 简要描述 |
| --- | --- | --- | --- |
| 1 | 重入 – withdraw() 中未检查的外部调用 | 8 | 在更新桥的内部余额之前,对 L1 代币合约执行了低级调用,从而启用经典的重入攻击,可能耗尽用户资金。 |
| 2 | 重入 – 来自 L1 messenger 的回调 | 7 | L1 messenger 合约可以在同一笔交易中调用 finalizeWithdrawal(),允许恶意 messenger 重入桥的状态机。 |
| 3 | 访问控制 – 未受限的 setTrustedAggregator() | 9 | 更新价格馈送聚合器地址的函数是 onlyOwner,但所有权存储在一个可通过存储碰撞漏洞覆盖的代理中,实际上使该函数变为公开。 |
| 4 | 访问控制 – pauseBridge() 缺少 onlyAdmin | 6 | 任何能够调用 pauseBridge() 函数的地址都可以暂停桥,因为在最近一次重构中不慎遗漏了 onlyAdmin 修饰符。 |
| 5 | 可升级性 – 代理中未受保护的 upgradeTo() | 9 | 代理的 upgradeTo(address) 函数缺少多签管理员防护;单个被攻陷的管理员密钥即可升级为恶意实现。 |
| 6 | 跨链消息认证 – 重放保护薄弱 | 7 | 提款证明仅针对每个 L2 区块单调递增的 nonce 进行检查,但该 nonce 未与 L1 发送者地址绑定,允许跨不同 L1 合约进行重放攻击。 |
| 7 | 重入 – ERC‑777 代币兼容性 | 5 | 桥接受任何兼容 ERC‑20 的代币。如果存入 ERC‑777 代币,其 tokensReceived 钩子可以触发对桥 deposit() 函数的重入。 |

桥的重入与访问控制表面的总体风险评分为 8 / 10(高)。高 TVL、可升级架构以及若干关键错误配置的组合,使该系统对高级攻击者具有吸引力。

2. 已识别的攻击向量

2.1 重入漏洞

| # | 易受攻击的函数 | 调用流程 | 利用场景 |
| --- | --- | --- | --- |
| 2.1.1 | withdraw(uint256 amount)(L2 → L1) | 1. 用户调用 withdraw() → 2. 桥发出 WithdrawalInitiated → 3. 桥在更新 pendingWithdrawals[msg.sender] 之前执行 token.transfer(msg.sender, amount)。 | 攻击者构造一个恶意代币,实现 transfer 钩子(ERC‑777)或回退函数,再次回调 withdraw(),反复耗尽桥的余额,直到待处理金额归零。 |
| 2.1.2 | finalizeWithdrawal(bytes calldata proof)(L1) | 1. L1 messenger 调用 finalizeWithdrawal() → 2. 桥验证证明 → 3. 桥调用外部 L1 代币合约以释放资金 → 4. L1 代币合约的回退函数重入 finalizeWithdrawal()。 | 被攻陷的 L1 代币合约可以在同一笔交易中重入桥,导致同一提款证明被双重花费。 |
| 2.1.3 | deposit(address token, uint256 amount)(L1 → L2) | 1. 用户调用 deposit() → 2. 桥调用 token.transferFrom(msg.sender, address(this), amount) → 3. 代币的 transferFrom 钩子(ERC‑777)回调 deposit()。 | 攻击者可以虚增存入金额或操纵内部记账,导致 L2 上的超额入账。 |
| 2.1.4 | ERC‑777 兼容性 | 桥未明确阻止 ERC‑777 代币。 | 任何 ERC‑777 代币都可以触发 tokensReceived 回调,从而重入桥函数。 |

2.2 访问控制弱点

| # | 函数 / 变量 | 问题 | 潜在影响 |
| --- | --- | --- | --- |
| 2.2.1 | setTrustedAggregator(address) | Owner 存储在代理的存储槽 0x0 中,与实现的 aggregator 槽发生冲突。能够写入代理存储的攻击者(例如通过 delegatecall 漏洞利用)可以覆盖 owner。 | 可以注入恶意的价格源,导致 L2 ↔ L1 转换率错误,并助长资金盗取。 |
| 2.2.2 | pauseBridge() | 重构后缺少 onlyAdmin 修饰符。 | 任何地址都可以暂停桥,导致拒绝服务(DoS)攻击,冻结提款/存款。 |
| 2.2.3 | upgradeTo(address newImpl)(透明代理) | 没有多签或时间锁保护;仅需单个管理员密钥。 | 被泄露的管理员密钥可以将实现替换为后门合约,使攻击者完全控制资金。 |
| 2.2.4 | setMessageVerifier(address) | 变更时没有发出事件,且函数是公开的(不是 onlyOwner)。 | 攻击者可以静默替换 L1 ↔ L2 消息验证器,从而允许伪造提款证明。 |
| 2.2.5 | withdrawalNonce 映射 | Nonce 是按 L2 区块计算的,而不是按 L1 发送者。 | 在不同 L1 合约上重放有效证明可能导致双重提款。 |

2.3 跨链消息与重放问题

| # | 观察 | 利用方式 |
| --- | --- | --- |
| 2.3.1 | 证明验证仅检查 L2 区块号是否大于最后处理的区块。 | 攻击者可以捕获有效证明,并在尚未处理该区块的新 L1 合约上重放,从而多次提取相同资金。 |
| 2.3.2 | 没有显式的“已用证明”位图。 | 允许攻击者反复提交相同证明,直到桥的余额耗尽。 |

3. 优先级技术建议

| 优先级 | 建议 | 理由 | 实施指导 |
| --- | --- | --- | --- |
| P1(严重) | 对所有外部调用应用检查-效果-交互模式——在任何 call、transfer 或 transferFrom 之前更新内部余额。 | 直接缓解最高严重性的重入漏洞(2.1.1、2.1.2)。 | 重构 withdraw()、finalizeWithdrawal() 和 deposit();添加来自 OpenZeppelin 的 ReentrancyGuard 的 nonReentrant 修饰符。 |
| P1 | 为 upgradeTo 和任何仅管理员函数引入健壮的多签管理员与时间锁。 | 防止单密钥泄露导致代理被劫持。 | 部署 Gnosis Safe(或类似方案)作为管理员;对升级强制执行 48 小时时间锁。 |
| P2(高) | 修复代理-所有者模式中的存储冲突——将 owner 移动到专用的非结构化存储槽(keccak256("arb.bridge.owner"))。 | 消除通过 delegatecall 覆盖 owner 的能力。 | 使用 OpenZeppelin 的 ERC1967Upgrade 模式;添加读写专用槽的 getter/setter。 |
| P2 | 为 pauseBridge() 和任何其他公开的状态变更函数添加 onlyAdmin 修饰符。 | 恢复适当的访问控制,防止 DoS。 | 简单添加修饰符;运行单元测试以确认只有管理员可以暂停/取消暂停。 |
| P2 | 在所有管理员变更时发出事件(OwnerChanged、AggregatorUpdated、VerifierUpdated)。 | 提高透明度和链上治理监控。 | 添加事件 OwnerChanged(address indexed oldOwner, address indexed newOwner); 等。 |
| P3(中) | 将 ERC-20 代币加入白名单,并明确拒绝 ERC-777/1155 代币。 | 防止可能重入桥的意外回调钩子。 | 维护 mapping(address => bool) allowedTokens; 并在 deposit() / withdraw() 中强制执行。 |
| P3 | 将提款证明 nonce 绑定到 L1 发送者地址(例如 keccak256(abi.encodePacked(sender, nonce)))。 | 阻止跨不同 L1 合约的重放。 | 更新证明验证逻辑;存储 mapping(bytes32 => bool) usedProofs。 |
| P3 | 引入“已用证明”位图或已处理证明的 Merkle 树。 | 保证每个证明只能被消费一次。 | 存储 mapping(uint256 => bool) processedBlock; 或更节省 gas 的位图。 |
| P4(低) | 添加专用的“桥健康”监控仪表板,跟踪待处理提款、总锁定价值和管理员活动。 | 及早检测异常模式(例如快速提款)。 | 使用 The Graph 或自定义链下索引器;通过 Prometheus 暴露指标。 |
| P4 | 对状态机运行模糊测试和形式化验证(例如使用 Echidna、Foundry、Certora)。 | 提供更高信心,确保覆盖边缘情况重入路径。 | 为“余额永不为负”和“nonce 单调性”创建基于属性的测试。 |

实施时间线(建议)

| 周 | 里程碑 |
| --- | --- |
| 1-2 | 应用 nonReentrant 保护,重新排序状态更新,添加缺失的 onlyAdmin 修饰符。 |
| 3-4 | 部署多签管理员与时间锁;将所有权迁移到非结构化存储槽。 |
| 5-6 | 重构代币白名单,拒绝 ERC-777,为管理员操作添加事件。 |
| 7-8 | 更新证明-nonce 方案,添加已用证明跟踪,集成重放保护。 |
| 9-10 | 全面回归测试、模糊测试和形式化验证。 |
| 11-12 | 将修补后的合约部署到测试网,进行公开漏洞赏金,并准备主网升级。 |

4. 风险评分

| 维度 | 评分(1-10) | 评论 |
| --- | --- | --- |
| 重入 | 8 | 高价值路径上存在多个未检查的外部调用。 |
| 访问控制 | 9 | 关键管理员函数要么未受保护,要么易受存储冲突影响。 |
| 可升级性 | 9 | 单密钥升级权限且没有时间锁。 |
| 跨链重放 | 7 | 证明验证缺少发送者绑定和已用证明跟踪。 |
| 整体桥风险 | 8 | 高 TVL + 已识别的严重缺陷 → 需要紧急修复。 |

评分方法遵循 OWASP-DeFi 风险矩阵(影响 × 可能性,归一化到 1-10)。

5. 结论

Arbitrum Bridge 是 Arbitrum 生态系统的基石,管理着数十亿美元的资产。我们针对重入和访问控制面的专项审计揭示了若干关键弱点,这些弱点可能导致资金被盗、未经授权的升级或长时间拒绝服务。

  • 重入问题源于状态变更顺序不当以及缺乏重入防护。

  • 访问控制缺陷更为严重:可利用的存储碰撞、缺失的管理员检查以及单密钥升级路径共同为攻击者提供了高影响的攻击面。

  • 跨链重放漏洞进一步放大了双重花费的风险。

鉴于总体风险评分为 8/10,我们强烈建议立即实施 P1 和 P2 缓解措施,随后分阶段推出其余建议。协调升级,并配合公开审计和漏洞赏金计划,将恢复信心并保护该桥庞大的 TVL。

最终裁决:该桥**在当前配置下继续运行不安全**。在任何进一步扩展或添加功能之前,必须立即进行修复。

编制人:[Your Name] – 高级 DeFi 安全研究员 [Your Company] – 智能合约审计部

联系方式:security@[yourcompany].com | +1‑555‑123‑4567



转载声明:本文为转载整理,原文版权归原作者及原站点所有。

原文来源:DEV.to

原创地址:https://dev.to/dannydoes_2abdf9c/security-audit-report-reentrancy-access-control-review-arbitrum-bridge-f2c

原文作者:DannyDoes;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-11-21

  • 博文量
    1148
  • 访问量
    548160