这篇讲述DASP TOP 10最后4类:、提前交易、时间操纵、短地址攻击和未知攻击

DASP Top 10,有个博主把这10类漏洞都大概描述了一下,写得真的是非常好,

repo大法!以太坊智能合约安全入门了解一下(上) 以太坊智能合约安全入门了解一下(下)

但是这篇文章还是偏向于代码向和实际用例,看心情翻牌讲

  1. Reentrancy - 重入
  2. Access Control - 访问控制
  3. Arithmetic Issues - 算术问题(整数溢出)
  4. Unchecked Return Values For Low Level Calls - 未严格判断不安全函数调用返回值
  5. Denial of Service - 拒绝服务
  6. Bad Randomness - 伪随机性
  7. Front Running - 提前交易
  8. Time manipulation - 时间操纵
  9. Short Address Attack - 短地址攻击
  10. 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列举了一个例子:

  1. 一个游戏今天午夜支付第一个玩家酬劳。
  2. 恶意矿工会尝试赢得比赛,并将时间戳设置为午夜。
  3. 午夜之前,矿工最终开采了该地块。由于实际的当前时间“足够接近”午夜(该块的当前设置时间戳),网络上的其他节点决定接受该块。

以下内容来自于 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

尽管此漏洞尚未被广泛利用,但它很好地证明了客户端与以太坊区块链之间的交互所引起的问题。

未知攻击