在跨链桥Cross-Chain Bridge的去中心化架构中“资产锁定与包装铸造Lock-and-Mint”是最为普及的资金跨链模型。用户在源链Source Chain将原生资产锁定在托管金库合约中链下中继网络Relayer Network捕获锁定事件后在目标链Destination Chain为该用户铸造对应的包装代币Wrapped Token。然而这一看似清晰的业务闭环却隐藏着致命的逻辑盲区——“代币映射Token Mapping鉴权缺失与假充值Fake Deposit漏洞”。一旦跨链端点合约缺乏严格的源链代币白名单校验或未对中继证明做强绑定攻击者便能自建恶意山寨代币Shitcoin并在目标链伪造映射关系诱使目标链合约铸造等额的优质高价值资产。在结合 GLM 5.3 开展的自动化静态分析与符号执行演练中我们成功挖掘并定位了这一隐藏在复杂跨链代理合约中的致命缺陷。一、漏洞机理代币映射假充值与证明伪造传统的充值入账逻辑通常依赖源链触发的Deposit或Locked事件。当桥接协议支持无许可添加跨链资产时代币映射关系的建立往往通过一个动态字典进行管理$$DestinationToken Mapping[SourceChainId][SourceTokenAddress]$$攻击者通常利用以下三种漏洞形态实现攻击穿透未校验源链代币有效性目标链接收到由中继器提交的跨链存单时仅检查了中继签名的有效性却未对源链合约地址做白名单过滤。攻击者在源链部署恶意代币合约并在该合约中伪造包含合法接收人地址的高额事件日志。多重映射冲突覆盖治理合约在绑定两链资产映射时未设置原子性锁或覆盖保护。攻击者利用重入或特定状态漏洞将高价值的合法包装代币映射指向自己掌控的恶意代币。重放攻击与 Nonce 证明缺位跨链操作缺少全局唯一的消息哈希或单次消费标记导致攻击者能够反复重放已验证的跨链证明。二、脆弱合约还原缺少资产认证的跨链端点以下是一个典型的存在代币映射假充值隐患的跨链端点合约实现VulnerableCrossChainEndpoint.sol// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; interface IMintableERC20 { function mint(address to, uint256 amount) external; function burn(address from, uint256 amount) external; } contract VulnerableCrossChainEndpoint { address public bridgeAdmin; address public trustedRelayer; // sourceChainId (sourceToken wrappedToken) mapping(uint256 mapping(address address)) public tokenMapping; // messageHash isProcessed mapping(bytes32 bool) public executedMessages; event AssetMinted(address indexed to, address indexed wrappedToken, uint256 amount); event MappingUpdated(uint256 indexed chainId, address indexed sourceToken, address indexed wrappedToken); error Unauthorized(); error AlreadyProcessed(); error InvalidSignature(); error UnsupportedToken(); constructor(address _relayer) { bridgeAdmin msg.sender; trustedRelayer _relayer; } /// notice 管理员配置代币映射 function registerTokenMapping( uint256 sourceChainId, address sourceToken, address wrappedToken ) external { if (msg.sender ! bridgeAdmin) revert Unauthorized(); tokenMapping[sourceChainId][sourceToken] wrappedToken; emit MappingUpdated(sourceChainId, sourceToken, wrappedToken); } /// notice 目标链执行跨链铸造 /// dev 严重缺陷并未校验 sourceToken 是否在注册映射中存在合法非零绑定 /// 并且如果允许用户自行传入未经审计的代币参数容易遭遇重放与假充值 function processCrossChainMint( uint256 sourceChainId, address sourceToken, address recipient, uint256 amount, uint256 nonce, bytes calldata relayerSignature ) external { bytes32 messageHash keccak256( abi.encodePacked(sourceChainId, sourceToken, recipient, amount, nonce, block.chainid) ); if (executedMessages[messageHash]) revert AlreadyProcessed(); // 验证中继器签名 if (!_verifyRelayer(messageHash, relayerSignature)) revert InvalidSignature(); executedMessages[messageHash] true; address wrappedToken tokenMapping[sourceChainId][sourceToken]; // 逻辑缺陷若 wrappedToken 映射未作严格防御且存在任意外部代理回调极易引发资产盗刷 if (wrappedToken address(0)) revert UnsupportedToken(); IMintableERC20(wrappedToken).mint(recipient, amount); emit AssetMinted(recipient, wrappedToken, amount); } function _verifyRelayer(bytes32 hash, bytes memory signature) internal view returns (bool) { bytes32 ethSignedHash keccak256( abi.encodePacked(\x19Ethereum Signed Message:\n32, hash) ); (bytes32 r, bytes32 s, uint8 v) splitSig(signature); return ecrecover(ethSignedHash, v, r, s) trustedRelayer; } function splitSig(bytes memory sig) internal pure returns (bytes32 r, bytes32 s, uint8 v) { require(sig.length 65, invalid signature); assembly { r : mload(add(sig, 32)) s : mload(add(sig, 64)) v : byte(0, mload(add(sig, 96))) } } }三、GLM 5.3 审计自动化扫描与语义诊断提示词在针对此类具有复杂跨链语义协议的审计工作中常规的语法静态分析器往往因为跨链上下文割裂而将高危逻辑判断为正常调用。我们设计了一套结构化的 GLM 5.3 审计提示词工程Prompt Engineering专门针对跨链存取证与映射路由进行语义流图溯源[Role]: 你是一名专精于以太坊虚拟机EVM与跨链互操作性协议CCIP/LayerZero的高级安全审计架构师。 [Context]: 当前被审计代码涉及两链之间的代币锁定与铸造流水线Lock-and-Mint。 [Instruction]: 1. 分析跨链端点函数 processCrossChainMint 中从入参 sourceToken 到最终执行 mint 的完整数据流。 2. 重点检查以下三类攻击面 a) 假充值伪造源链代币源头Source Origin是否具备抗女巫与不可伪造证明 b) 映射混淆tokenMapping 映射表是否支持未经验证的代币注入 c) 精度失配源链代币精度Decimals如 6 位 USDC与目标链包装代币精度如 18 位在转换计算时是否存在向下溢出或虚假放大 3. 输出形式 - 漏洞等级Critical / High / Medium / Low - 缺陷调用链追踪Call Trace - 概念验证PoC攻击用例编写 - 安全加固后的修复代码GLM 5.3 在对包含上述模式的代码执行符号扫描后给出了精准的漏洞分析报告[Critical] 跨链源资产合法性断言缺失与精度攻击风险机理分析虽然合约校验了trustedRelayer的签名但假设中继器节点仅通过监听源链特定事件打包消息若源链的事件发生在一个伪造的同名 ERC-20 合约中中继器在未校验源链代币合约哈希的情况下直接进行了签名导致恶意代币在目标链直接铸造出核心资产。更关键的是如果两端代币精度不匹配如 6 精度换 18 精度未作归一化缩放将引发数十万倍的假充值套利。四、安全防御方案与加固实现防御跨链代币假充值的核心在于**“两端强绑定、全局白名单、精度归一化与双向事件对账”**。加固后的生产级跨链执行合约应当具备源链与目标链代币的双向不可篡改绑定在注册映射时同时校验源链代币的合约地址哈希、字节码指纹以及代币精度。严格的精度缩放处理器Decimals Normalizer将所有跨链金额统一折算为 18 位标准精度进行核算与限额风控结算时再反向还原为目标代币原生精度。重放与紧急断路器机制在目标链引入带有时间锁Timelock的大额提款审核机制阻断瞬间的大额代币伪造。以下为安全加固的防假充值实现// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; interface IERC20Metadata { function decimals() external view returns (uint8); } interface IMintableERC20Secure { function mint(address to, uint256 amount) external; function decimals() external view returns (uint8); } contract SecureCrossChainEndpoint { address public owner; address public trustedRelayer; struct TokenConfig { address wrappedToken; uint8 sourceDecimals; uint8 targetDecimals; bool isActive; } // sourceChainId (sourceToken TokenConfig) mapping(uint256 mapping(address TokenConfig)) public verifiedTokens; mapping(bytes32 bool) public executedHashes; event TokenWhitelisted(uint256 indexed chainId, address indexed sourceToken, address indexed wrappedToken); event CrossChainMinted(address indexed recipient, address indexed wrappedToken, uint256 originalAmount, uint256 mintedAmount); error NotAuthorized(); error TokenNotWhitelisted(); error HashAlreadyExecuted(); error InvalidSigner(); error DecimalOverflow(); constructor(address _relayer) { owner msg.sender; trustedRelayer _relayer; } function whitelistTokenPair( uint256 sourceChainId, address sourceToken, address wrappedToken, uint8 sourceDecimals ) external { if (msg.sender ! owner) revert NotAuthorized(); require(sourceToken ! address(0) wrappedToken ! address(0), zero address); uint8 targetDecimals IMintableERC20Secure(wrappedToken).decimals(); verifiedTokens[sourceChainId][sourceToken] TokenConfig({ wrappedToken: wrappedToken, sourceDecimals: sourceDecimals, targetDecimals: targetDecimals, isActive: true }); emit TokenWhitelisted(sourceChainId, sourceToken, wrappedToken); } function executeMint( uint256 sourceChainId, address sourceToken, address recipient, uint256 rawAmount, uint256 nonce, bytes calldata signature ) external { TokenConfig memory config verifiedTokens[sourceChainId][sourceToken]; if (!config.isActive) revert TokenNotWhitelisted(); bytes32 executionHash keccak256( abi.encode(sourceChainId, sourceToken, recipient, rawAmount, nonce, block.chainid) ); if (executedHashes[executionHash]) revert HashAlreadyExecuted(); executedHashes[executionHash] true; // 校验中继签名 bytes32 ethHash keccak256( abi.encodePacked(\x19Ethereum Signed Message:\n32, executionHash) ); if (!_verify(ethHash, signature)) revert InvalidSigner(); // 精确换算代币精度防止精度放大攻击 uint256 mintAmount _normalizeDecimals(rawAmount, config.sourceDecimals, config.targetDecimals); IMintableERC20Secure(config.wrappedToken).mint(recipient, mintAmount); emit CrossChainMinted(recipient, config.wrappedToken, rawAmount, mintAmount); } function _normalizeDecimals(uint256 amount, uint8 srcDec, uint8 dstDec) internal pure returns (uint256) { if (srcDec dstDec) { return amount; } else if (srcDec dstDec) { uint256 factor 10 ** (dstDec - srcDec); return amount * factor; } else { uint256 factor 10 ** (srcDec - dstDec); return amount / factor; } } function _verify(bytes32 hash, bytes memory sig) internal view returns (bool) { if (sig.length ! 65) return false; bytes32 r; bytes32 s; uint8 v; assembly { r : mload(add(sig, 32)) s : mload(add(sig, 64)) v : byte(0, mload(add(sig, 96))) } return ecrecover(hash, v, r, s) trustedRelayer; } }通过引入严格的双向元数据绑定与精度归一化计算智能合约切断了任何未授权代币映射注入的物理路径使跨链桥从源头杜绝了因代币伪造导致的资产被掏空风险。
阅读完成 · 觉得有帮助?