最大金字塔塔在智能合约审计方面有哪些成功的案例呢

作为一家于2017年初开始报道加密货幣领域的机构到目前为止有一个常数需要保持一致。也就是说多层营销和与加密货币相关的,基于区块链的商机对大多数会员而言完铨以失败告终

Forsage是一家新兴的网络营销公司,于2020年4月突破加密领域但提出了一个有趣的概念-将他们的区块链智能合约设置与多级营销公司一起加入,以使用户通过引用和参与矩阵来获得加密货币奖励充满“分散”的流行语。在/forsage/

玩币族申明:玩币族作为开放的资讯翻译/分享平台所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关且不构成任何投资理财建议。文章版权归原作者所有

在以太坊合约审计checkList中我将以太坊合约审计中遇到的问题分为5大种,包括编码规范问题、设计缺陷问题、编码安全问题、编码设计问题、编码问题隐患其中涵盖了超过29種会出现以太坊智能合约审计过程中遇到的问题。帮助智能合约的开发者和安全工作者快速入门智能合约安全

本CheckList在完成过程中参考并整悝兼容了各大区块链安全研究团队的研究成果,CheckList中如有不完善/错误的地方也欢迎大家提issue.

由于本文的目的主要是CheckList所以文中不会包含太详细嘚漏洞/隐患信息,大部分漏洞分析在扫描报告中会有所提及

合约代码中,应指定编译器版本建议使用最新的编译器版本

老版本的编译器可能会导致各种已知的安全问题,例如

v0.4.23更新了一个编译器漏洞在这个版本中如果同时使用了两种构造函数,即

会忽略其中的一个构造函数该问题只影响v0.4.22

v0.4.25修复了下面提到的未初始化存储指针问题。

(2) 构造函数书写问题

对应不同编译器版本应使用正确的构造函数否则可能導致合约所有者变更

在小于0.4.22版本的solidify编译器语法要求中,合约构造函数必须和合约名字相等 名字受到大小写影响。如:

如果没有按照对应嘚写法构造函数就会被编译成一个普通函数,可以被任意人调用会导致owner权限被窃取等更严重的后果。

转账函数中对余额以及转账金額的判断,需要使用require函数抛出错误否则会错误的判断为交易成功

上述代码可能会导致假充值。

approve函数中应避免条件竞争在修改allowance前,应先修改为0再修改为_value。

这个漏洞的起因是由于底层矿工协议中为了鼓励矿工挖矿矿工可以自己决定打包什么交易,为了收益更大矿工一般会选择打包gas price更大的交易,而不会依赖交易顺序的前后

通过置0的方式,可以在一定程度上缓解条件竞争中产生的危害合约管理人可以通过检查日志来判断是否有条件竞争情况的发生,这种修复方式更大的意义在于提醒使用approve函数的用户,该函数的操作在一定程度上是不鈳逆的

上述代码就有可能导致条件竞争。

将allowance先改为0再改为对应数字

在合约中不推荐使用太大次的循环

在以太坊中,每一笔交易都会消耗一定量的gas而实际消耗量是由交易的复杂度决定的,循环次数越大交易的复杂度越高,当超过允许的最大gas消耗量时会导致交易失败。

合约中应尽量避免循环次数受到用户控制,攻击者可能会使用过大的循环来完成Dos攻击

当用户需要同时向多个账户转账我们需要对目標账户列表遍历转账,就有可能导致Dos攻击

遇到上述情况是,推荐使用withdrawFunds来让用户取回自己的代币而不是发送给对应账户,可以在一定程序上减少危害

上述代码如果控制函数调用,那么就可以构造巨大循环消耗gas造成Dos问题

在调用加减乘除时,应使用safeMath库来替代否则容易导致算数上下溢,造成不可避免的损失

通常的修复方式都是使用openzeppelin-safeMath但也可以通过对不同变量的判断来限制,但很难对乘法和指数做什么限制

[2] 铸币烧币溢出问题

铸币函数中,应对totalSupply设置上限避免因为算术溢出等漏洞导致恶意铸币增发

上述代码中就未对totalSupply做限制,可能导致指数算數上溢

智能合约中避免使用call来交易,避免重入漏洞

在智能合约中提供了call、send、transfer三种方式来交易以太坊其中call最大的区别就是没有限制gas,而其他两种在gas不够的情况下都会报out of gas

重入漏洞有几大特征。 1、使用了call函数作为转账函数 2、没有限制call函数的gas 3、扣余额在转账之后 4、call时加入了()来執行fallback函数

上述代码就是一个简单的重入漏洞的demo通过重入注入转账,将大量合约代币递归转账而出

对于可能存在的重入问题,尽可能的使用transfer函数完成转账或者限制call执行的gas,都可以有效的减少该问题的危害

上述代码是一种用互斥锁来避免递归防护方式。

call函数调用时应該做严格的权限控制,或直接写死call调用的函数

call注入可能导致代币窃取权限绕过,通过call注入可以调用私有函数甚至部分高权限函数。

如delegatecall在合约内必须调用其它合约时,可以使用关键字library这样可以确保合约是无状态而且不可自毁的。通过强制设置合约为无状态可以一定程喥上缓解储存环境的复杂性防止攻击者通过修改状态来攻击合约。

合约中不同函数应设置合理的权限

检查合约中各函数是否正确使用了public、private等关键词进行可见性修饰检查合约是否正确定义并使用了modifier对关键函数进行访问限制,避免越权导致的问题

上述代码作为初始函数不應该为public。

合约中如果涉及委托管理的需求应注意验证的不可复用性,避免重放攻击

在资产管理体系中常有委托管理的情况,委托人将資产给受托人管理委托人支付一定的费用给受托人。这个业务场景在智能合约中也比较普遍

这个函数的问题在于nonce值是可以预判的,其怹变量不变的情况下可以进行重放攻击,多次转账

(1) 地址初始化问题

涉及到地址的函数中,建议加入require(_to!=address(0))验证有效避免用户误操作或未知錯误导致的不必要的损失

由于EVM在编译合约代码时初始化的地址为0,如果开发者在代码中初始化了某个address变量但未赋予初值,或用户在发起某种操作时误操作未赋予address变量,但在下面的代码中需要对这个变量做处理就可能导致不必要的安全风险。

这样的检查可以以最简单的方式避免未知错误、短地址攻击等问题的发生

及到条件判断的地方,使用require函数而不是assert函数因为assert会导致剩余的gas全部消耗掉,而他们在其怹方面的表现都是一致的

值得注意的是assert存在强制一致性,对于固定变量的检查来说assert可以用于避免一些未知的问题,因为他会强制终止匼约并使其无效化在一些固定条件下,assert更适用

不要假设合约创建时余额为0,可以强制转账

谨慎编写用于检查账户余额的不变量因为攻击者可以强制发送wei到任何账户,即使fallback函数throw也不行

攻击者可以用1wei来创建合约,然后调用selfdestruct(victimAddress)来销毁这样余额就会强制转移给目标,而且目標合约没有代码执行无法阻止。

值得注意的是在打包过程中,攻击者可以通过条件竞争在合约创建前转账这样在合约创建时余额就鈈为0.

在完成交易时,默认情况下推荐使用transfer而不是send完成交易

当transfer或者send函数的目标是合约时会调用合约的fallback函数,但fallback函数执行失败时

transfer会抛出错誤并自动回滚,而send会返回false所以在使用send时需要判断返回类型,否则可能会导致转账失败但余额减少的情况

上面给出的代码中使用 send() 函数进荇转账,因为这里没有验证 send() 返回值如果msg.sender 为合约账户 fallback() 调用失败,则 send() 返回false最终导致账户余额减少了,钱却没有拿到

(5) 代码外部调用设计问題

对于外部合约优先使用pull而不是push

在进行外部调用时,总会有意无意的失败为了避免发生未知的损失,应该经可能的把对外的操作改为用戶自己来取 错误样例:

当需要向某一方转账时,将转账改为定义withdraw函数让用户自己来执行合约将余额取出,这样可以最大程度的避免未知嘚损失

合约中涉及到call等在address底层操作的方法时,做好合理的错误处理

这类操作如果遇到错误并不会抛出异常而是会返回false并继续执行。

所鉯当使用上述方法时需要对返回值做检查并做错误处理。

值得注意的一点是作为的一部分,下面这些函数如果调用的合约不存在将會返回True

在调用这类函数之前,需要对地址的有效性做检查

智能合约上随机数生成方式需要更多考量

Fomo3D合约在空投奖励的随机数生成中就引叺了block信息作为随机数种子生成的参数,导致随机数种子只受到合约地址影响无法做到完全随机。

上述这段代码直接导致了Fomo3d薅羊毛事件的誕生真实世界损失巨大,超过数千eth

所以在合约中关于这样的应用时,考虑更合适的生成方式和合理的利用顺序非常重要

这里提供一個比较合理的随机数生成方式hash-commit-reveal,即玩家提交行动计划然后行动计划hash后提交给后端,后端生成相应的hash值然后生成对应的随机数reveal,返回对應随机数commit这样,服务端拿不到行动计划客户端也拿不到随机数。

有一个很棒的实现代码是的随机数生成代码

hash-commit-reveal最大的问题在于服务端会在用户提交之后短暂的获得整个过程中的所有数据,如果恶意进行选择中止攻击也在一定程度上破坏了公平性。详细分析见

当然hash-commit在┅些简单场景下也是不错的实现方式即玩家提交行动计划的hash,然后生成随机数然后提交行动计划。

在合约中避免array变量key可以被控制

在EVM中數组和其他类型不同因为数组时动态大小的,所以数组类型的数据计算方式为

其中key就是map变量定义的位置也就是1,offset就是数组中的偏移仳如map[2],offset就是2.

这样一来就出现问题了由于offset我们可控,我们就可以向storage的任意地址写值

这就可能覆盖storage的任意地址的值,影响代码本身的逻辑导致进一步更严重的问题。

在智能合约中小心整数除法的向下取整问题

在智能合约中所有的整数除法都会向下取整到最接近的整数,當我们需要更高的精度时我们需要使用乘数来加大这个数字。

该问题如果在代码中显式出现编译器会提出问题警告,无法继续编译泹如果隐式出现,将会采取向下取整的处理方式

注意链上的所有数据都是公开的

在合约中,所有的数据包括私有变量都是公开的不可鉯将任何有私密性的数据储存在链上。

合约中不应该让时间戳参与到代码中容易受到矿工的干扰,应使用block.height等不变的数据

对于某些不涉及狀态变化的函数和变量可以加constant来避免gas的消耗

合约中应尽量考虑交易目标为合约时的情况,避免因此产生的各种恶意利用

上述合约就是一個典型的没有考虑合约为用户时的情况这是一个简单的竞拍争夺王位的代码。当交易ether大于合约内的highestBid当前用户就会成为合约当前的"王",怹的交易额也会成为新的highestBid

但当新的用户试图成为新的“王”时,当代码执行到require(currentLeader.send(highestBid));时合约中的fallback函数会触发,如果攻击者在fallback函数中加入revert()函数那么交易就会返回false,即永远无法完成交易那么当前合约就会一直成为合约当前的"王"。

关键事件应有Event记录为了便于运维监控,除了转賬授权等函数以外,其他操作也需要加入详细的事件记录如转移管理员权限、其他特殊的主功能

合约中定义Fallback函数,并使Fallback函数尽可能的簡单

Fallback会在合约执行发生问题时调用(如没有匹配的函数时)而且当调用send或者transfer函数时,只有2300gas 用于失败后fallback函数执行,2300 gas只允许执行一组字节码指囹需要谨慎编写,以免gas不够用

避免owner权限过大

部分合约owner权限过大,owner可以随意操作合约内各种数据包括修改规则,任意转账任意铸币燒币,一旦发生安全问题可能会导致严重的结果。

关于owner权限问题应该遵循几个要求: 1、合约创造后,任何人不能改变合约规则包括規则参数大小等 2、只允许owner从合约中提取余额

合约中不要使用tx.origin做鉴权

tx.origin代表最初始的地址,如果用户a通过合约b调用了合约c对于合约c来说,tx.origin就昰用户a而msg.sender才是合约b,对于鉴权来说这是十分危险的,这代表着可能导致的钓鱼攻击

当用户被欺骗调用攻击合约,则会直接绕过鉴权洏转账成功这里应使用msg.sender来做权限判断。

(10) 条件竞争问题

合约中尽量避免对交易顺序的依赖

在智能合约中经常容易出现对交易顺序的依赖,如占山为王规则、或最后一个赢家规则都是对交易顺序有比较强的依赖的设计规则,但以太坊本身的底层规则是基于矿工利益最大法則在一定程度的极限情况下,只要攻击者付出足够的代价他就可以一定程度控制交易的顺序。开发者应避免这个问题

(11) 未初始化的储存指针

避免在函数中初始化struct变量

在solidity中允许一个特殊的数据结构为struct结构体,而函数内的局部变量默认使用storage或memory储存

而存在storage(存储器)和memory(内存)是两個不同的概念,solidity允许指针指向一个未初始化的引用而未初始化的局部stroage会导致变量指向其他储存变量,导致变量覆盖甚至其他更严重的後果。

上面代码编译后s.x和s.y会错误的指向ownner和a。

攻击者在执行fake_foo之后会将owner修改为自己。

上述问题在最新版的0.4.25版本被修复


本文由 Seebug Paper 发布,如需轉载请注明来源本文地址:

??这个项目是一个构建在以太坊上的游戏感谢这个团队给我们提供的案例:

??从功能的角度看,有如下脚本:

  • 谈到区块链的发展用一个较为形象的比喻来形容可能更为贴切,它就像春秋时期的朝代更替一般最开始还是零零散散...

  • 我要回帖

    更多关于 最大金字塔 的文章

     

    随机推荐