您的位置: > 比特币行情> 正文

打印本文             

By:小白@慢雾安全团队

背景概述

上周写了智能合约安全审计入门篇 —— 重入漏洞,这次我们接着来说一个同样很经典的漏洞 —— 溢出漏洞

前置知识

首先我们还是先来看看溢出是什么:

算术溢出(arithmetic overflow)或简称为溢出(overflow)分为两种:上溢和下溢。所谓上溢是指在运行单项数值计算时,当计算产生出来的结果非常大,大于寄存器或存储器所能存储或表示的能力限制就会产生上溢,例如在 solidity 中,uint8 所能表示的范围是 0 - 255 这 256 个数,当使用 uint8 类型在实际运算中计算 255 + 1 是会出现上溢的,这样计算出来的结果为 0 也就是 uint8 类型可表示的最小值。同样的,下溢就是当计算产生出来的结果非常小,小于寄存器或存储器所能存储或表示的能力限制就会产生下溢。例如在 Solidity 中,当使用 uint8 类型计算 0 - 1 时就会产生下溢,这样计算出来的值为 255 也就是 uint8 类型可表示的最大值。

如果一个合约有溢出漏洞的话会导致计算的实际结果和预期的结果产生非常大的差异,这样轻则会影响合约的正常逻辑,重则会导致合约中的资金丢失。但是溢出漏洞是存在版本限制的,在 Solidity < 0.8 时溢出不会报错,当 Solidity >= 0.8 时溢出会报错。所以当我们看到 0.8 版本以下的合约时,就要注意这个合约可能出现溢出问题。

漏洞示例

看了前置知识我相信大家对溢出漏洞都有一定的了解了,下面我们来结合合约代码来深入了解溢出漏洞:

  •  

// SPDX-License-Identifier: MITpragma solidity ^0.7.6;

contract TimeLock { mapping(address => uint) public balances; mapping(address => uint) public lockTime;

function deposit() external payable { balances[msg.sender] += msg.value; lockTime[msg.sender] = block.timestamp + 1 weeks; }

function increaseLockTime(uint _secondsToIncrease) public { lockTime[msg.sender] += _secondsToIncrease; }

function withdraw() public { require(balances[msg.sender] > 0, "Insufficient funds"); require(block.timestamp > lockTime[msg.sender], "Lock time not expired");

uint amount = balances[msg.sender]; balances[msg.sender] = 0;

(bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Failed to send Ether"); }}

漏洞分析

我们可以看到,TimeLock 合约充当了时间保险库。用户可以将代币通过 deposit 函数存入该合约并锁定,且至少一周内不能提现。当然用户也可以通过 increaseLockTime 函数来增加存储时间,用户在设定的存储期限到期前是无法提取 TimeLock 合约中锁定的代币的。首先我们发现这个合约中的 increaseLockTime 函数和 deposit 函数具有运算功能,并且合约支持的版本是:0.7.6 向上兼容,所以这个合约在算数溢出时是不会报错的,所以我们这里就可以判断这个合约是可能存在溢出漏洞的,这里可利用的函数有两个,一个是 increaseLockTime 函数,一个是 deposit 函数。我们先来分析这两个函数内参数可影响的范围再来决定如何发起攻击:

1. deposit 函数存在两个运算操作,第一个是影响用户存入的余额 balances 的,这里传入的参数是可控的所以这里会有溢出的风险,另一个是影响用户的锁定时间 lockTime 的,但是这里的运算逻辑是每次调用 deposit 存入代币时会给 lockTime 增加一周,由于这里的参数不可控所以这个运算不会存在溢出风险。

2. increaseLockTime 函数是根据用户传入的 _secondsToIncrease 参数来进行运算从而改变用户的存入代币的锁定时间的,由于这里的 _secondsToIncrease 参数是可控的,所以这里有溢出的风险。

综上所述,我们发现可利用的参数有两个,分别为 deposit 函数中的 balances 参数 increaseLockTime 函数中的 _secondsToIncrease 参数

我们先来看 balances 参数,如果要让这个参数溢出我们需要有足够的资金存入才可以(需要 2^256 个代币存入才能导致 balances 溢出并归零),如果要利用这个溢出漏洞的话,我们把大量资金存入自己的账户并让自己的账户的 balances 溢出并归零从而清空自己的资产,我觉得在坐的各位没有人会这么做吧。所以这个参数可以认为在攻击者的角度是不可用的。

我们再看 _secondsToIncrease 参数,这个参数是我们调用 increaseLockTime 函数来增加存储时间时传入的,这个参数可以决定我们什么时候可以将自己存入并锁定的代币从合约中取出,我们可以看到这个参数在传入之后是直接与账户对应的锁定时间 lockTime 进行运算的,如果我们操纵 _secondsToIncrease 参数让他在与 lockTime 进行运算后得到的结果产生溢出并归零的话这样我们是不是就可以在存储日期到期前将自己账户中的余额取出了呢?

下面我们来看看攻击合约:

攻击合约

  •  

contract Attack { TimeLock timeLock;

constructor(TimeLock _timeLock) { timeLock = TimeLock(_timeLock); }

fallback() external payable {}

function attack() public payable { timeLock.deposit{value: msg.value}(); timeLock.increaseLockTime( type(uint).max + 1 - timeLock.lockTime(address(this)) ); timeLock.withdraw(); }}

这里我们将使用 Attack 攻击合约先存入以太后利用合约的溢出漏洞在存储未到期的情况下提取我们在刚刚 TimeLock 合约中存入并锁定的以太:

1. 首先部署 TimeLock 合约;

2. 再部署 Attack 合约并在构造函数中传入 TimeLock 合约的地址;

3. 调用 Attack.attack 函数,Attack.attack 又调用 TimeLock.deposit 函数向 TimeLock 合约中存入一个以太(此时这枚以太将被 TimeLock 锁定一周的时间),之后 Attack.attack 又调用 TimeLock.increaseLockTime 函数并传入 uint 类型可表示的最大值(2^256 - 1)加 1 再减去当前 TimeLock 合约中记录的锁定时间。此时 TimeLock.increaseLockTime 函数中的 lockTime 的计算结果为 2^256 这个值,在 uint256 类型中 2^256 这个数存在上溢所以计算结果为 2^256 = 0 此时我们刚刚存入 TimeLock 合约中的一个以太的锁定时间就变为 0 ;

4. 这时 Attack.attack 再调用 TimeLock. withdraw 函数将成功通过 block.timestamp > lockTime[msg.sender] 这项检查让我们能够在存储时间未到期的情况下成功提前取出我们刚刚在 TimeLock 合约中存入并锁定的那个以太。

下面是攻击流程图:

solidity

修复建议

到这里相信大家对溢出漏洞都有自己的理解了,那么下面我们就以开发者和审计者的角度来分析如何预防溢出漏洞和如何快速找出溢出漏洞:

(1)作为开发者

1. 使用 SafeMath 来防止溢出;

2. 使用 Solidity 0.8 及以上版本来开发合约并慎用 unchecked 因为在 unchecked 修饰的代码块里面是不会对参数进行溢出检查的;

3. 需要慎用变量类型强制转换,例如将 uint256 类型的参数强转为 uint8 类型由于两种类型的取值范围不同也可能会导致溢出。

(2)作为审计者

1. 首先查看合约版本是否在 Solidity 0.8 版本以下或者是否存在 unchecked 修饰的代码块,如果存在则优先检查参数的溢出可能并确定影响范围;

2. 如果合约版本在 Solidity 0.8 版本以下则需要查看合约是否引用了 SafeMath;

3. 如果使用了 SafeMath 我们需要注意合约中有没有强制类型转换,如果有的话则可能会存在溢出的风险;

4. 如果没有使用 SafeMath 且合约中存在算术运算的我们就可以认为这个合约是可能存在溢出风险的,在实际审计中还要结合实际代码来看。


Yuga Labs 或对元宇宙/Web3 格局产生重大影响

撰文:Pedro Herrera,DappRadar 撰稿人

编辑:南风

撰文时,Yuga Labs 的 6 个 NFT 系列已经占到了以太坊上 NFT 市值的 43%。

上图:Yuga Labs 的 6 个 NFT 项目的市值,数据截至2022年3月29日

不到一年前,也就是2021 年 4 月 28 日,Yuga Labs 推出了「无聊猿游艇俱乐部」(BAYC),这是 NFT 历史上最具影响力的项目之一。BAYC 与CryptoPunks一起引领了 NFT 热潮,在 2021 年见证了创纪录的交易量。这两个 NFT 项目的重要性可以说超越了区块链领域,达到了一种文化现象的地位。CryptoPunks 和 Bored Apes (无聊猿) 已经通过知名拍卖行佳士得 (Christie’s) 和苏富比 (Sotheby’s) 成为主流,并成为数十位名人在社交媒体上的头像。因此,当 Yuga Labs 宣布收购 CryptoPunks 和 Meebits 的知识产权时,整个加密社区陷入一阵狂热。

收购 CryptoPunks 知识产权几天之后,Yuga Labs 通过公布其元宇宙计划后再次登上头条,包括其备受期待的代币ApeCoin以及 BAYC 生态系统元宇宙项目Otherside。Yuga Labs 经历了从最初推出 BAYC 这个当时铸造价只有0.08 ETH(约合 120 美元) 的 NFT 收藏品到发展成为一个领先的 Web3.0 品牌。Yuga Labs 目前的估值已达 40 亿美元,并建立了一个充满活力的元宇宙生态系统。本报告将从不同角度阐述 Yuga Labs 公告的影响,并阐述这些最近的行动在 Web3 和元宇宙的前景中的含义。

关键信息

Yuga Labs 成为了 Web3 领域的主导力量,其 6 个 NFT 系列的总市值约为 81 亿美元,占以太坊前 100 名 NFT 收藏品项目市值的43%

ApeCoin代币通过其 23 亿美元的市值加强了 Yuga Labs 的品牌定位。

由 Anderseen Horowitz (a16z) 和 Animoca Brands 牵头的4.5 亿美元投资(估值 40 亿美元) 进一步推动了 Yuga Labs 的元市场计划。

目录

Yuga Labs 的 NFTs 占据以太坊上 NFT 地板市值的 43%

CryptoPunks 和 Meebits 的底价在收购后上涨

作为 BAYC 生态的经济引擎,ApeCoin 代币的市值接近 23 亿美元

4.5 亿美元的投资提振了 BAYC 元宇宙

对 Web3 领域产生的影响

Yuga Labs 的 NFTs 占据以太坊上 NFTs 地板市值的 43%

在收购 Larva Labs 拥有的 CryptoPunks 和 Meebits 的知识产权之前,Yuga Labs 已经控制着整个加密领域最具影响力的名字之一:Bored Ape Yacht Club(BAYC)。BAYC 系列包含 10,000 个 NFT,成为了 NFT 头像运动的代名词。该项目受到 NFT 社区的广泛欢迎,并很快被著名的 NFT 收藏家所寻找,最显著的就是好莱坞、体育和音乐名人。这些名人的高度参与给这个 NFT 系列带来了一种与现实世界中的奢侈品牌相似的独特性。

除了10,000 个「无聊猿」NFT,Yuga Labs 的 BAYC 生态系统还包含其他3 个额外的 NFT 项目

The Bored Ape Kennels (BAKC,无聊猿狗舍俱乐部)

The Mutant Ape Yacht Club (MAYC,突变猿游艇俱乐部)

The Bored Ape Chemistry Club (BACC,无聊猿化学俱乐部)

这些 NFT 系列展示了 Yuga Labs 实现的高实用性。「无聊猿」NFT 的持有者们已经免费获得了BAKC(总计 10,000 个) 和突变血清 (BACC),比例为 1:1 (外加 Gas 费)。

编者注:BACC 总共包含 10,000 份 NFT 突变血清 (Mutant Serum) ,由 3 种不同的突变血清组成:M1 Mutant Serum、M2 Mutant Serum 和 Mega Mutant Serum。BAYC 无聊猿的持有者在空投到 BACC 突变血清之后,可以选择将 BACC 血清与 BAYC 无聊猿进行结合以铸造 MAYC 突变猿 NFT,也可以选择在 OpenSea 等平台上将 BACC NFT 进行出售。注入 M1 或 M2 血清的 Bored Ape (无聊猿) 外观会有较轻微的变化,相比之下 Mega Mutant Serum 所带来的突变外观会更为疯狂以及难以预测,因此这种血清的价格更高。此外,血清在使用后将会消失。

BAYC 生态系统是整个 NFT 领域中最强大的群体之一。根据 DappRadar 的 NFT 价值估算工具,BAYC、BAKC、MAYC 以及 BACC这 4 个 NFT 系列的市值估计为 55 亿美元,这一市值占了以太坊前 100 名 NFT 收藏品系列的底价市值的29%。如下图所示:

Yuga Labs 或对元宇宙/Web3 格局产生重大影响

撰文:Pedro Herrera,DappRadar 撰稿人...

关于我们

币安下载官方app|币安iOS版|币安安卓版|币安电脑网页版

  • 用户支持
  • 帮助中心
  • 服务条款
微信二维码
币安官网渠道 数字区块链交易平台 Powered by binance
QR code