区块链安全问题解析

2023年08月02日更新 2 人订阅
专栏简介 Upbit交易所大额ETH被盗事件详细分析 Ronin Network侧链被盗6.25亿美金流向分析 | 零时科技 零时科技 | 被盗6.1亿美金,Poly Network 被攻击复盘分析 2019年区块链安全事件总结,全球损失超60亿美元 安全建议 | 资金盘项目ETDP转移5000ETH跑路事件详情分析 零时科技 | 智能合约安全系列文章之反编译篇 慢雾:29 枚 Moonbirds NFT 被盗事件溯源分析 美链BEC合约漏洞技术分析 FTN 合约漏洞分析 成都链安:3月发生较典型安全事件超『17』起,以太坊Defi前景与风险并存,诈骗活动有所增加 铸币疑云 —— Paid Network 被盗细节分析 零时科技 | 以太坊链上互助保险平台Nexus Mutual被攻击事件分析 PeckShield:硬核技术解析,bZx协议遭黑客漏洞攻击始末 智能合约语法层面漏洞详解 交易重放+管理漏洞—2000万枚OP被盗事件分析 近7000万美元被盗:Curve被攻击事件分析 技术分析 Lendf.me 被攻击,ERC777到底该不该用? 零时科技:DeFi 项目 Lendf.Me 遭黑客攻击复盘分析 Poker EOS被盗 2万多EOS事件启示 - 谈私钥安全 回顾史上最大智能合约漏洞事件 — The DAO事件 16万美元资产被盗竟是乌龙事件? | Yeld.finance“闪电贷攻击”事件 EOS DApp 随机数漏洞分析2 - EOSDice 随机数被操控 EOS DApp 随机数漏洞分析1 - EOSDice 随机数被预测 EOS DApp 漏洞分析 - inline action 交易回滚攻击 以太坊DAO攻击解决方案代码解析 区块链共识安全 - 51%攻击浅析 【安全】Fomo3D死亡3分钟的交易攻击分析 币安交易所比特币被窃漏洞分析 千万美元被盗 —— DeFi 平台 MonoX Finance 被黑分析 零时科技:勒索软件 Shade 宣布停止运营, 并发布75万个解密密钥 zkSNARK 合约「输入假名」漏洞致众多混币项目爆雷 零知识证明 - zkSNARK应用的Nullifier Hash攻击 区块链安全100问 |​ 第四篇:保护数字钱包安全,防止资产被盗 使用历史权重难度(HWD)预防POW 51%算力攻击 区块链入门-51%攻击原理

美链BEC合约漏洞技术分析

  • Tiny熊
  • 发布于 2018-04-25 10:13
  • 阅读 59722

这两天币圈链圈被美链BEC智能合约的漏洞导致代币价值几乎归零的事件刷遍朋友圈。这篇文章就来分析下BEC智能合约的漏洞

这两天币圈链圈被美链BEC智能合约的漏洞导致代币价值几乎归零的事件刷遍朋友圈。这篇文章就来分析下BEC智能合约的漏洞

漏洞攻击交易

我们先来还原下攻击交易,这个交易可以在这个链接查询到。 我截图给大家看一下:

攻击者向两个账号转移57896044618...000.792003956564819968个BEC,相当于BEC凭空进行了一个巨大的增发,几乎导致BEC价格瞬间归零。 下面我们来分析下这个攻击过程。

合约漏洞分析

我们先来看看BEC智能合约的代码, BEC在合约中加入一个批量转账的函数,它的实现如下:

function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
    uint cnt = _receivers.length;
    uint256 amount = uint256(cnt) * _value;
    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;

这个函数的作用是,调用者传入若干个地址和转账金额,在经过一些条件检查之后,对msg.sender的余额进行减操作,对每一个对每一个传入的地址进行加操作,以实现BEC的转移。 问题出在 uint256 amount = uint256(cnt) * _value; 这句代码,当传入值_value过大时(接近uint256的取值范围的最大值),uint256 amount = uint256(cnt) * _value计算时会发生溢出,导致amount实际的值是一个非常小的数(此时amount不再是cnt * _value的实际值),amount很小,也使得后面对调用者余额校验可正常通过(即require(_value > 0 && balances[msg.sender] >= amount)语句通过)。

我们来结合实际攻击交易使用的参数来分析一下:

batchTransfer的参数_value值为16进制的800000000000000000000...,参数_receivers数组的大小为2,相乘之后刚好可超过uint256所能表示的整数大小上限,引发溢出问题amount实际的值为0,后面的转账操作实际上msg.sender的余额减0, 而对两个账号进行了加16进制的800000000000000000000...,最终的结果是相当于增发了2 * 16进制的800000000000000000000...

实际上对于这种整数溢出漏洞,最简单的方法是采用 SafeMath 数学计算库来避免。有趣的是BEC智能合约代码中,其实其他的都使用了SafeMath, 而关键的uint256 amount = uint256(cnt) * _value却没有使用。 心痛程序员,也心痛韭菜。这句代码改为uint256 amount = _value.mul(uint256(cnt));就可以防止溢出问题

所以在做加减乘除的时候请记得一定使用:SafeMath,代码在这里

溢出补充说明

溢出补充说明为小专栏订阅用户福利,小专栏的文章内介绍了什么时候会发生上溢,什么时候会发生下溢,并且给出了代码事例。 大家可请前往我的小专栏阅读。

知识星球深入浅出区块链做好的区块链技术问答社区,欢迎来提问,作为星球成员福利,成员可加入区块链技术付费交流群。 深入浅出区块链 - 打造高质量区块链技术博客,学区块链都来这里,关注知乎微博 掌握区块链技术动态。

Solidity最大可以处理256位数字, 最大值为 2**256 - 1, 对(2**256 - 1) 加1的结果会溢出归0。2**255 乘2也同样会溢出归0。 对无符号类型最小值是零,对零做减1会得到 (2**256 - 1)。

我们用一段代码验证一下:

pragma solidity 0.4.20;
contract TestFlow {
    uint256 public zero = 0;
    uint256 public max = 2**256 - 1;
    uint256 public mm = 2**255;

    function subUnderFlow() public constant returns (uint) {
        uint256 a =  zero - 1;
        return a;
    }

    function addOverFlow() public constant returns (uint) {
        uint256 a =  max + 1;
        return a;
    }

    function mulOverFlow() public constant returns (uint) {
        uint256 a =  mm * 2;
        return a;
    }
}

合约部署和运行,之前已经经过很多次,我直接贴运行结果:

-->

学习中如遇问题,欢迎到区块链技术问答提问,这里有老师为你解惑。

点赞 2
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论