智能合约漏洞介绍3
这篇讲述DASP TOP 10最后4类:、提前交易、时间操纵、短地址攻击和未知攻击
DASP Top 10,有个博主把这10类漏洞都大概描述了一下,写得真的是非常好,
repo大法!以太坊智能合约安全入门了解一下(上) 以太坊智能合约安全入门了解一下(下)
但是这篇文章还是偏向于代码向和实际用例,看心情翻牌讲
- Reentrancy - 重入
- Access Control - 访问控制
- Arithmetic Issues - 算术问题(整数溢出)
- Unchecked Return Values For Low Level Calls - 未严格判断不安全函数调用返回值
- Denial of Service - 拒绝服务
- Bad Randomness - 伪随机性
- Front Running - 提前交易
- Time manipulation - 时间操纵
- Short Address Attack - 短地址攻击
- Unknown Unknowns - 其他未知
提前交易
所谓提前交易,再介绍伪随机性的漏洞介绍中已经有所提及,它产生的前提是,矿工对具有更高gas的交易有更高的优先级。我以前看过一篇SCI,上面就有提到这个类型的漏洞问题,比如以太坊上有一个悬赏令,当A有正确答案时,A如果发布了包含答案的交易,被B捕捉到了,B抄A的答案,然后给这个交易附上更高的gas,那么矿工就会优先打包B的答案,结果A的答案交易反而排在B之后,气气!
实际案例
Bancor
抢先就是这样一种攻击。该术语起源于股票市场,可追溯到交易台之间手工进行纸质交易的时代。经纪人会收到客户的买入特定股票的订单,然后将自己的买入订单放在前面。这样,经纪人可以从价格上涨中受益,而其客户却会因此而牺牲。自然,这种做法是不公平的,并被取缔。
节选自:https://hackernoon.com/front-running-bancor-in-150-lines-of-python-with-ethereum-api-d5e2bfd0d798
其实Bancor就是这个原理,Bancor以我粗略的理解,就是有点类似代币交易所,或者说智能合约代币股票市场,当我们发现有人大量入Bancor的时候,我们抢先插在这个交易前面,然后等大量入Bancor的交易完成之后,肯定价格就会涨上去,那我们就稳赚不赔啊,高!
大佬甚至直接给出了代码:https://github.com/bogatyy/bancor/blob/master/one_frontrun.py
文中也提到了Bancor采取了一些治标不治本的措施,当然这也没办法,本来这个漏洞就确实不好解决。
预防方法
还是上文那篇SCI提到过,可以首先声明自己有了答案,锁定题目,然后再发送带有答案的交易,即使抄袭也不行了,这个方法有点像前面提到的解决伪随机性的commit-reveal的方法。
时间操纵
时间操纵也部分属于伪随机数漏洞,毕竟block.timestamp(也有别名now)也是一个区块变量。
如果矿工持有合同的股份,他可以通过为他正在开采的区块选择合适的时间戳来获得优势。
—— Nicola Atzei,Massimo Bartoletti和Tiziana Cimoli
DASP TOP 10列举了一个例子:
- 一个游戏今天午夜支付第一个玩家酬劳。
- 恶意矿工会尝试赢得比赛,并将时间戳设置为午夜。
- 午夜之前,矿工最终开采了该地块。由于实际的当前时间“足够接近”午夜(该块的当前设置时间戳),网络上的其他节点决定接受该块。
以下内容来自于 https://ethfans.org/posts/comprehensive-list-of-common-attacks-and-defense-part-6#2
真实的例子
GovernMental
GovernMental 是一个很久以前的庞氏骗局,积累了相当多的 Ether。它也容易受到基于时间戳的攻击。合约会在一轮内支付给最后一个加入合约的玩家(需要加入至少一分钟)。因此,作为玩家的矿工可以调整时间戳(未来的时间,使其看起来像是一分钟过去了),以显示玩家加入已经超过一分钟(尽管现实中并非如此)。关于这方面的更多细节可以在 Tanya Bahrynovska 的 以太坊安全漏洞史 中找到。
预防技术
区块时间戳不应该用于熵源或产生随机数——也就是说,它们不应该是游戏判定胜负或改变重要状态(如果假定为随机)的决定性因素(无论是直接还是通过某些推导)。
时效性强的逻辑有时是必需的;即解锁合约(时间锁定),几周后完成 ICO 或到期强制执行。有时建议使用 block.number
(参见 Solidity 文档)和平均区块时间来估计时间;即,10 秒的区块时间运行 1 周,约等于,60480 个区块。因此,指定区块编号来更改合约状态可能更安全,因为矿工无法轻松操纵区块编号。BAT ICO合约就采用这种策略。
如果合约不是特别关心矿工对区块时间戳的操纵,这可能是不必要的,但是在开发合约时应该注意这一点。
短地址攻击
The service preparing the data for token transfers assumed that users will input 20-byte long addresses, but the length of the addresses was not actually checked.
—— Paweł Bylica
短地址攻击感觉应该不能算EVM的锅?短地址攻击简单来说,就是一般我们默认我们的地址是20字节的,程序会将地址(预期的20字节长度)加上12个零字节,使其成为32字节长。
那如果我们构造出一个这样的地址:0x1234567890123456789012345678901234567800
,在数据发送的时候,如果碰见一个这样的函数 transfer(address _to, uint256 _amount)
,那么我发送对应的数据为
账户地址(前补 0 补齐 32 字节)0000000000000000000000001234567890123456789012345678901234567800
0x1(前补 0 补齐 32 字节)0000000000000000000000000000000000000000000000000000000000000001
但是如果我恶意的将账户地址数据改成
00000000000000000000000012345678901234567890123456789012345678
那么,我这个后一数据就会把0填充过来,整个数据就变成
0000000000000000000000001234567890123456789012345678901234567800
0000000000000000000000000000000000000000000000000000000000000100(最后的00是EVM填充的)
预防方法
目前我也不太分得清这到底是客户端还是EVM的锅,但是EVM的处理逻辑事实上并没有太大问题,但是如果在代码层去修复这个问题,比如加入一个参数长度验证,就会产生如下问题:Smart Contract Short Address Attack Mitigation Failure。
尽管此漏洞尚未被广泛利用,但它很好地证明了客户端与以太坊区块链之间的交互所引起的问题。
未知攻击
无