是黑客太强了,还是EOS太弱了?

自六月份EOS主网之后,亲身经历和见证过EOS DApp一路走来的艰辛。被黑客以各种各样方式攻击过的DAPP,总的损失规模至少上千万了。一直以来,都想对所有被攻击过的DAPP,以及攻击方式做一个汇总。

因为前人花大的代价踩的坑,得到的教训,应该总结好,避免之后的人再犯。

作者:币乎 jc1991

首先引用下 imeos 总结的安全漏洞盘点:

这些造成损失的漏洞,可以归为合约代码漏洞,和随机数算法使用不当的两种问题。

1. 智能合约代码问题

代码溢出之类的漏洞 (狼人杀案例)

这个就不多说了,漏洞细节,就是当时eos版本中的 asset 类的乘法存在 检查溢出无效的问题。 而代码中,依赖 asset 的代码做溢出检查,或者压根就没考虑做溢出检查。 导致了整型溢出,出现了致命而无法修复的bug。

这点,只要主要在合约代码中的数值计算部分,做详细的 eosio_assert 断言检查就可避免。关键还是细心写代码哈。

未检查 code == eosio.token

这个问题受害面还是比较广的,从 EOS bet、newdex、 以及后来的 cast 项目,都是因为没有检查转账的来源,而蒙受大额损失,从以上的列表看出,这条经验是好百万巨款买来的。

项目方,利用转账通知回调transfer,来执行业务,但是这个 transfer通知,有可能来自 非 eosio.token的 (俗称假币 假EOS), 所以对 code == eosio.token 的判断,就非常的重要。

转账通知 未判断 to == _self

这个问题,暴漏在 EOS bet 第二次被攻击的时候。损失也是500万以上。

转账通知,有个特点,就是不仅仅你收到转账的会收到通知,任何人收到转账的时候,都可以通知你,他收到了转账。

比如,张三收到了李四 100 EOS 的转账,于是张三 告诉王五,“收到 100 EOS 转账”。

王五,没有判断 “收款人 等于王五”,于是以为是自己收到了 100 EOS的转账。

原因就是这样。 项目方,实际上没有收到 真正的 EOS, 只是收到了 一条EOS 到账通知,但收款人还不是项目方。

如何对任意人发起转账通知呢?

只需要在转账中加入一条代码即可:

这样,你想通知谁,就通知谁。 此时要是对面没判断收款人,那么很可能就被你黑了噢。

2. 伪随机代码中存在的一些问题

伪随机数算法中的可计算参数

之前不少概率随机游戏的项目方,采用了链上伪随机方案,也即纯粹使用区块链上的数据来做游戏开奖的随机数种子。

但是,由于使用不当,有了种种被黑的结局。

类似的链上伪随机算法,我贴几张图作为参考:

以及广泛被引用的github代码:

https://github.com/generEOS/eosio.random/blob/master/random.cpp

以上案例,都有一个共同的特点,就是采用了 tapos_block_prefix, tapos_block_num 做为随机数种子。

但是啊,这两个值,其实是依赖于 过去的区块。也就是说,它们是能算出来的,当这个关键的参数,能够被计算出来的时候,所谓的随机数算法,就不是随机了。

黑客可以提前计算好结果,保证百分百胜率。

除了,tapos_block_prefix, tapos_block_num, 还有 当前transacation_id 下面就分享下,这几个值如何算。

tapos_block_prefix, tapos_block_num 以及 transacation id 怎么计算 ?

tapos 有个定义是 Transactions as Proof-of-Stake (TaPOS)

它是指定一个过去的区块( ref_block_num ),用来做 Proof-of-Stake的。

而代码中使用的 tapos_block_prefix 和tapos_block_num, 正是由这个 ref_block_num 算出来的。

查看push action 说明,可以看到发起一个普通的action时,其中 ref_block_num, 是由客户端指定的!

有人会说,我平时发起action的时候,并没有指定过 ref_block_num啊?

其实,当你没指定 ref_block_num 的时候,我们使用的 cleos 或eosjs 客户端,会帮我们默认指定一个:

翻客户端的代码,它告诉你,如果用户没指定ref_block_num,会帮你取一个, 取的是 last_irreversible_block_id,

也就是get info 中返回的,上一个不可逆区块的id。

也就是,有了ref_block_num ,我们就可以拿到 tapos_block_prefix 和tapos_block_num 了:

最后 说下 transacation_id ,

transacation_id , 是一笔交易的唯一id,是一个hash值,看起来好像是随机不可预测的啊。

于是有人拿它做随机数,然后就没然后了。

这个值,跟你发起的 transacation 有唯一关联,

所以是个可计算的值。

计算方法如下:

直接 read_transaction 拿到 当前 transacation的数据,然后 sha256 就得到了 transacation_id了。

3. 为什么利用延时交易,tapos_block_prefix, tapos_block_num 依然被破解了

有的项目,采用延时交易来异步开奖,伪随机算法里,用到了 tapos_block_prefix, tapos_block_num, 时间,用户名,奖池金额等信息。

这样的伪随机算法,看起来好像没毛病,用到了未来的数据,似乎无法预测,但是真的是这样么?

时间的话,知道了你延迟多少秒后,直接往上加就行了,用户名是确定的,奖池金额这个虽然是动态的,但是如果变动的频率不是非常快,快到每分每妙都在变,那么在短时间内,可以视为是定值。

所以关键还在于 tapos_block_prefix, tapos_block_num 。

延迟交易中的 tapos_block_prefix, tapos_block_num, 和普通交易中的 tapos_block_prefix, tapos_block_num 计算方式有所不同。

普通交易,通过客户端制定 ref_block_num ,然后计算出来。

而延迟交易中,看EOS相关代码得知,直接使用head_block_id 做为 ref_block_num 。

也就是说,当前区块头,就是ref_block_nu。

知道这点后,就好办了,有多种办法可以拿到head_block ,比如说 直接 get_info

拿到了 head_block_num 之后,在get_block 信息,可以直接得到

拿到了这两个参数,又知道了随机数算法,理论上,就能够预测能不能中奖了。

直接在合约里写代码判断,能中奖就发送交易,不能就跳过。

总结 tapos_block_prefix, tapos_block_num,慎用为随机数算法参数,如果非要用,可以采用发起连续的两次延时交易。因为延迟交易中的 head_block_id 跟你延迟多少秒没关系,是构造这个延迟交易的时候,就设定好了的。

PS 千万别在你的伪随机算法里,加入一些可控参数,比如EOS余额。EOS Dice就是因为这个被攻破了两次。

4. 同步开奖时被利用智能合约钩子,回滚交易

早期被黑的项目中,还存在一些 “错误的实践” , 也值得提一下。

第一种,是同步开奖,同步开奖有个问题,就是黑客可以轻松的破解你,一个简单的思路是,直接拉取你的项目code,然后部署一个合约A, 然后用合约B跟这个A合约玩,假如和A合约玩赢了,A合约会给B转账,在B的转账通知那边写一个转账通知回调,一旦赢了,就和你的项目玩。 这样是必胜的。

第二种,是发回执,被对方拒绝,导致回滚整个交易。

一个错误案例是: 开奖 -> 给对方发一个 receipt action, 告诉对方你中奖没中奖, 于是对方,直接针对这个receipt 写一个回调,当你告诉他输了之后,他可以拒绝,回滚这次开奖, 这个好像被叫做 “重放攻击” , 避免的方法,就是 receipt 之类的通知,可以采用异步的。

5. 为何不开源也被撸?

目前大多数菠菜类项目方,是不敢开源的,一是怕竞争,而是怕暴漏问题。

这个不好评判,我个人还是喜欢开源的。

被撸的项目方,其实大部分也都没有开源,那么为什么还是被撸了呢? 这里简单分享下。

首先,你合约代码都部署都上链了,对于有能力撸你的那些技术大神,这里其实没多少秘密可言。无非是读源代码和编译后代码的区别而已。

项目的代码,在编译过后,部署到了链上。取回的步骤如下。

第一步,通过 get code 取回。可以得到 abi 文件和 wast 文件。abi文件,可以看到接口信息,和猜测整个合约代码的大致结构。

翻译 wast 文件了,找出你的随机数算法。 下面几张图,是简单的示例。

简而言之,你开源或不开源,对那些黑客来说,其实都一样的。

关键还是写代码时,不要留下问题。不要去踩那些坑。不要轻易使用可以被拿到的参数做关键部分的随机数算法参数。

6. onchain调用

EOS Bet 在第一次被攻击的时候,表面上,是没有检查

code == eosio.token , 实际上,还有一个值得一提的细节。

那就是,对方这个 transfer action,并没有暴漏在 abi中,也就是客户端是没办法直接调用的。

但是黑客是直接调用的。那么是如果做到的呢。

原来,abi 并不是必须的。

一旦你的code中有这个action,那么就算在abi文件中,把这个 action接口删除了,企图留下外面的人不知道的 “后门”。

实际上这个 action 还是可以被调用。

有两种方法,

第一种,就是直接在另一个智能合约里发起调用。

第二种,就是改造下你的客户端。不要在push aciton的时候,去调用abi。

改造的细节过于技术,有兴趣的去参考这个 https://zhuanlan.zhihu.com/p/42903901?utm_source=wechat_session&utm_medium=social

总结, abi 只是接口和数据描述文件,就算你代码不部署 abi,也不影响合约代码正常工作。 所以,如果你的智能合约,仅仅是用来和其他智能合约交互,而不是面向客户的用户(cleos、eosjs),那 abi 都可以不用部署。

作者币乎原文地址:

https://bihu.com/article/1827909?from=timeline&isappinstalled=0

参考文章

累计薅走数百万,EOS Dapps已成黑客提款机?

BET被黑客攻击始末,实锤还原作案现场和攻击手段

震惊! EOSBet又被攻击了。损失高达500万。攻击手法竟是这样?

EOS-based dApp EosRoyale hacked. $60,000 stolen from operational wallet

EODIDEC 随机数被攻破

EOS Cast 被假EOS变种盗走7万多EOS

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容