区块链安全—溢出的BEC漏洞
字数 1656 2025-08-22 12:22:30

区块链安全:BEC代币整数溢出漏洞分析与复现

一、BEC代币简介

BEC(Beauty Chain)是世界上第一个专注于美容生态系统的区块链平台,基于Beauty Chain的创新开放平台,汇集了美容行业上下游应用。BEC代币是该生态系统中使用的通证,用于激励用户、工作人员、应用开发者及上下游企业。

关键数据

  • 2018年2月上线OKEx交易所
  • 发行总量:70亿枚
  • 市值峰值:280亿美元
  • 漏洞爆发时间:2018年4月22日
  • 合约地址:0xc5d105e63711398af9bbff092d4b6769c82f793d

二、合约代码架构分析

BEC合约基于ERC20标准实现,采用多层继承结构:

1. 基础合约

SafeMath库

library SafeMath {
    function mul(uint256 a, uint256 b) internal constant returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }
    // 其他安全运算函数...
}

ERC20Basic合约

  • 定义代币基础接口
  • 包含totalSupplybalanceOftransfer等基本功能

BasicToken合约

  • 实现ERC20Basic接口
  • 使用SafeMath进行安全运算
  • 管理地址余额映射mapping(address => uint256) balances

StandardToken合约

  • 扩展ERC20标准功能
  • 实现transferFromapprove等授权功能
  • 管理授权额度映射mapping (address => mapping (address => uint256)) internal allowed

2. 功能扩展合约

Ownable合约

contract Ownable {
    address public owner;
    
    function transferOwnership(address newOwner) onlyOwner public {
        require(newOwner != address(0));
        owner = newOwner;
    }
    // 其他所有权管理函数...
}

Pausable合约

contract Pausable is Ownable {
    bool public paused = false;
    
    modifier whenNotPaused() { require(!paused); _; }
    
    function pause() onlyOwner whenNotPaused public {
        paused = true;
    }
    // 其他暂停控制函数...
}

PausableToken合约

  • 继承StandardToken和Pausable
  • 重写转账相关函数,添加暂停检查
  • 关键漏洞函数batchTransfer
function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
    uint cnt = _receivers.length;
    uint256 amount = uint256(cnt) * _value; // 漏洞点:未使用SafeMath
    require(cnt > 0 && cnt <= 20);
    require(_value > 0 && balances[msg.sender] >= amount);
    
    balances[msg.sender] = balances[msg.sender].sub(amount);
    for (uint i = 0; i < cnt; i++) {
        balances[_receivers[i]] = balances[_receivers[i]].add(_value);
        Transfer(msg.sender, _receivers[i], _value);
    }
    return true;
}

BecToken合约

  • 设置代币基本信息(名称、符号、小数位)
  • 初始化总供应量:70亿 × 10¹⁸

三、漏洞原理分析

1. 漏洞位置

batchTransfer函数中,amount的计算未使用SafeMath的安全乘法:

uint256 amount = uint256(cnt) * _value; // 不安全运算

2. 整数溢出条件

当满足以下条件时会发生整数溢出:

cnt * _value > 2²⁵⁶ - 1

计算结果会回绕到极小的值甚至0

3. 具体攻击参数

攻击者可构造以下参数实现攻击:

  • _value = 2²⁵⁵ = 57896044618658097711785492504343953926634992332820282019728792003956564819968
  • cnt = 2

计算:

amount = 2 × 2²⁵⁵ = 2²⁵⁶ ≡ 0 (mod 2²⁵⁶)

4. 绕过安全检查

虽然合约有余额检查:

require(_value > 0 && balances[msg.sender] >= amount);

但当amount溢出为0时,攻击者即使余额不足也能通过检查

四、漏洞复现步骤

1. 部署合约

  • 使用Solidity 0.4.16编译器
  • 部署BecToken合约
  • 验证初始余额分配

2. 准备攻击

  1. 选择两个接收地址(如A和B)
  2. 设置攻击参数:
    • _receivers: [A, B]
    • _value: 2²⁵⁵

3. 执行攻击

调用batchTransfer函数:

contract.batchTransfer(
    ["0x147...160c", "0x4b0...2db"],
    "57896044618658097711785492504343953926634992332820282019728792003956564819968"
);

4. 验证结果

  • 攻击者余额不变(因为amount=0)
  • 接收方A和B各获得2²⁵⁵ BEC代币
  • 合约总供应量被恶意增发

五、漏洞修复方案

1. 立即修复方案

  1. 暂停合约交易(已实施)
  2. 部署新合约并迁移资产

2. 代码层面修复

// 使用SafeMath进行乘法运算
uint256 amount = uint256(cnt).mul(_value);

3. 长期预防措施

  1. 所有算术运算强制使用SafeMath
  2. 严格参数校验:
    require(_value > 0 && _value <= MAX_ALLOWED_VALUE);
    
  3. 引入静态分析工具检测潜在漏洞
  4. 进行全面的安全审计

六、经验教训

  1. 安全开发实践

    • 所有算术运算必须使用安全库
    • 对用户输入参数进行严格验证
    • 特别关注批量操作函数的安全性
  2. 合约设计原则

    • 遵循"最小权限原则"
    • 重要功能添加速率限制
    • 考虑使用升级模式应对未知漏洞
  3. 测试要求

    • 必须包含边界值测试
    • 进行整数溢出专项测试
    • 模拟极端情况下的合约行为
  4. 应急响应

    • 建立漏洞披露和响应机制
    • 准备合约暂停和资产迁移方案
    • 保持与交易所的紧急沟通渠道

七、参考资源

  1. BEC合约源代码
  2. Solidity安全文档
  3. ERC20标准
  4. 智能合约安全最佳实践
区块链安全:BEC代币整数溢出漏洞分析与复现 一、BEC代币简介 BEC(Beauty Chain)是世界上第一个专注于美容生态系统的区块链平台,基于Beauty Chain的创新开放平台,汇集了美容行业上下游应用。BEC代币是该生态系统中使用的通证,用于激励用户、工作人员、应用开发者及上下游企业。 关键数据 : 2018年2月上线OKEx交易所 发行总量:70亿枚 市值峰值:280亿美元 漏洞爆发时间:2018年4月22日 合约地址:0xc5d105e63711398af9bbff092d4b6769c82f793d 二、合约代码架构分析 BEC合约基于ERC20标准实现,采用多层继承结构: 1. 基础合约 SafeMath库 : ERC20Basic合约 : 定义代币基础接口 包含 totalSupply 、 balanceOf 和 transfer 等基本功能 BasicToken合约 : 实现ERC20Basic接口 使用SafeMath进行安全运算 管理地址余额映射 mapping(address => uint256) balances StandardToken合约 : 扩展ERC20标准功能 实现 transferFrom 和 approve 等授权功能 管理授权额度映射 mapping (address => mapping (address => uint256)) internal allowed 2. 功能扩展合约 Ownable合约 : Pausable合约 : PausableToken合约 : 继承StandardToken和Pausable 重写转账相关函数,添加暂停检查 关键漏洞函数 : batchTransfer BecToken合约 : 设置代币基本信息(名称、符号、小数位) 初始化总供应量:70亿 × 10¹⁸ 三、漏洞原理分析 1. 漏洞位置 在 batchTransfer 函数中, amount 的计算未使用SafeMath的安全乘法: 2. 整数溢出条件 当满足以下条件时会发生整数溢出: 计算结果会回绕到极小的值甚至0 3. 具体攻击参数 攻击者可构造以下参数实现攻击: _value = 2²⁵⁵ = 57896044618658097711785492504343953926634992332820282019728792003956564819968 cnt = 2 计算: 4. 绕过安全检查 虽然合约有余额检查: 但当 amount 溢出为0时,攻击者即使余额不足也能通过检查 四、漏洞复现步骤 1. 部署合约 使用Solidity 0.4.16编译器 部署BecToken合约 验证初始余额分配 2. 准备攻击 选择两个接收地址(如A和B) 设置攻击参数: _receivers : [ A, B ] _value : 2²⁵⁵ 3. 执行攻击 调用 batchTransfer 函数: 4. 验证结果 攻击者余额不变(因为amount=0) 接收方A和B各获得2²⁵⁵ BEC代币 合约总供应量被恶意增发 五、漏洞修复方案 1. 立即修复方案 暂停合约交易(已实施) 部署新合约并迁移资产 2. 代码层面修复 3. 长期预防措施 所有算术运算强制使用SafeMath 严格参数校验: 引入静态分析工具检测潜在漏洞 进行全面的安全审计 六、经验教训 安全开发实践 : 所有算术运算必须使用安全库 对用户输入参数进行严格验证 特别关注批量操作函数的安全性 合约设计原则 : 遵循"最小权限原则" 重要功能添加速率限制 考虑使用升级模式应对未知漏洞 测试要求 : 必须包含边界值测试 进行整数溢出专项测试 模拟极端情况下的合约行为 应急响应 : 建立漏洞披露和响应机制 准备合约暂停和资产迁移方案 保持与交易所的紧急沟通渠道 七、参考资源 BEC合约源代码 Solidity安全文档 ERC20标准 智能合约安全最佳实践