高危逻辑漏洞-Web3+Web2前端结合的ABI任意调用实现链上交易免gas
字数 1495 2025-08-22 12:22:54
Web3与Web2前端结合的ABI任意调用漏洞分析
1. 智能合约与DAPP交互基础
1.1 智能合约交互流程
-
编写与编译:
- 使用Solidity编写智能合约代码
- 编译为EVM可执行的bytecode
- 生成ABI(Application Binary Interface)描述文件
-
部署:
- 通过交易将bytecode部署到链上
- 获得合约专属地址
-
调用:
- DAPP通过交易调用合约地址
- 根据ABI确定调用的函数和参数
1.2 ABI详解
- ABI定义:标准化的智能合约接口描述格式
- 包含内容:
- 合约提供的函数
- 数据结构(状态变量和事件)
- 作用:使外部应用能准确与智能合约交互
- 生成方式:编译器自动生成
1.3 ABI编码(Calldata)
- 组成:
0x+ 函数选择器哈希前4字节 + 参数值(0填充) - 生成工具:
- https://abi.hashex.org
- 解码工具:
- https://abi.yiew.cn
- https://calldata.swiss-knife.xyz/decoder
2. 漏洞案例背景
2.1 项目场景
- 类型:DeFi场景
- 功能:支持申购和赎回Token
- 特点:
- 使用Magic Link钱包(无助记词,邮箱登录)
- 项目方承担gas费用
- 也支持用户自带钱包(自付gas)
2.2 交易流程分析
-
申购操作:
- 用户点击申购
- 前端生成ABI编码(calldata)
- 调用后端接口发送交易
-
关键数据:
data:ABI编码(calldata)to:目标合约地址signatures:交易签名
-
实际调用链:
- 用户钱包 → 项目方合约的execTransaction方法 → 实际交易合约的subscribe方法
3. 漏洞原理与利用
3.1 漏洞本质
后端未校验调用的合约地址和方法是否符合业务规则,导致可以:
- 修改
to字段指向任意合约地址 - 修改
data字段调用任意方法 - 利用项目方支付的gas费用执行任意交易
3.2 漏洞利用步骤
-
定位关键JS代码:
- 通过控制台日志找到ABI编码生成点
- 定位
encodeFunctionData调用
-
篡改ABI编码:
- 修改
data字段为其他方法的ABI编码 - 修改
to字段为其他合约地址
- 修改
-
示例攻击:
-
Mint攻击:
// 调用任意合约的mint方法 data = "0x40c10f19000000000000000000000000176791d147bef3f62dadde535604f339a1758e4400000000000000000000000000000000000000000000000000000000000f4240" to = "0x8e913be54763a751942a1af9d2f3d04a2d8078e3" // 任意ERC20合约地址 -
Burn攻击:
// 调用任意合约的burn方法 data = "0x9dc29fac000000000000000000000000b891626e1b89c572d2a9d3324473d0b280f45cad0000000000000000000000000000000000000000000000000000000000989680"
-
3.3 潜在危害
-
任意合约调用:
- 调用mint方法凭空生成代币
- 调用burn方法销毁他人代币
- 调用transfer方法转移资金
-
Gas费用滥用:
- 利用项目方支付的gas执行大量交易
- 可能耗尽项目方gas预算
4. 漏洞修复方案
4.1 修复建议
-
合约地址白名单:
- 后端维护允许调用的合约地址列表
- 校验
to字段必须在白名单内
-
方法限制:
- 对允许调用的方法进行限制
- 校验
data中的方法选择器是否符合预期
-
参数校验:
- 对ABI编码中的参数进行校验
- 确保参数值在合理范围内
4.2 实现示例
// 后端伪代码
function validateTransaction(address to, bytes calldata data) {
require(whitelist[to], "Contract not in whitelist");
bytes4 selector = bytes4(data);
require(
selector == SUBSCRIBE_SELECTOR ||
selector == REDEEM_SELECTOR,
"Invalid method"
);
// 进一步参数校验...
}
5. 总结与最佳实践
5.1 关键教训
-
永远不要信任前端输入:
- 所有来自前端的合约调用请求必须严格校验
- 包括合约地址、方法、参数等
-
最小权限原则:
- 只开放必要的合约和方法给前端调用
- 限制调用范围和权限
-
gas费用设计:
- 为第三方支付gas的场景设计合理的限制机制
- 防止gas滥用
5.2 开发建议
-
完整的调用链审计:
- 从用户操作到最终链上交易的完整路径审计
- 确保每个环节都有适当的校验
-
防御性编程:
- 假设所有外部输入都可能被篡改
- 实施多层校验机制
-
监控与告警:
- 监控异常交易模式
- 设置调用频率和gas消耗阈值告警