以太坊EIP-1283 sstore 重入漏洞拆解分析

昨天下班的时侯刚好在 etherscan 上查代码,瞄了一眼君士坦丁堡硬分叉的倒计时,发现离激活刚好还差 10000 个区块,抓紧了这 10 秒的时间,截图留念。


10k to go

今天上午,安全审计团队 ChainSecurity 猝不及防的发布了一份漏洞分析简报。为此,以太坊核心开发团队触发了紧急响应,正式宣布君士坦丁堡升级延期,重启时间未定。
……回想昨天自己发朋友圈时的激动兴奋,感觉被狠狠打了脸。

下午读完 ChainSecurity 的简报,写的很干练,可惜对不熟悉 ETH 的朋友们不够友好,需要梳理半天的逻辑。所以抖个胆,自己写个更详细的拆解,我也是新入行,有错误的话,见谅。

sstore 重入漏洞拆解分析

理解原合约

ChainSecurity 给的被攻击案例很有代表性,完整的被攻击合约点此查看

这是个 “双人共享收款钱包” 合约(以下简称:钱包合约),我们来举个正常情况下的使用例子:

  1. 为地址 「小A」、「小B」 登记一个编号为 1 的共享钱袋
调用钱包合约功能:init(钱袋1 , 小A, 小B)
  1. 设定收到 ETH 后的分账比例为 小A:小B = 7:3
调用钱包合约功能:updateSplit(钱袋1, 70)
// 即「小A」获得 70%,「小B」获得其余部分
  1. 「小C」向钱包合约地址的钱袋 1 支付 10ETH
「小C」调用钱包合约功能:deposit(钱袋1) + 10ETH
// 此次交互 tx 携带 10ETH 的金额
// 此时钱包合约地址余额:10ETH
// 其中,登记为「钱袋1」的余额:10ETH
  1. 清算 钱袋1 的余额,合约自动依照设定比例支付给「小A」、「小B」
调用钱包合约功能:splitFunds(钱袋1)
// 最终,以下两个转账函数 (transfer) 将依次执行
A.transfer(「钱袋1余额」 * 「分账比」 / 100);
B.transfer(「钱袋1余额」 * (100 - 「分账比」) / 100);
//「小A」获得 (10ETH * 70 / 100) = 7ETH
//「小B」获得 (10ETH * 30 / 100) = 3ETH

So far, so good.
感叹下以太坊的灵活性,公平公正的分帐,童叟无欺。

攻击搭建

那么,哪里会有问题呢???
ChainSecurity 给出了攻击的具体方式,完整的攻击者合约点此查看

「黑客X」将此合约部署到链上后,可获得一个攻击者合约地址(以下简称:攻击合约)。

我们继续有请善良的「小A」「小B」「小C」,重新操作以上的 [步骤1~步骤3]

  1. 「黑客X」登场,为「攻击合约」与「黑客X」登记了钱袋2,并对此钱袋支付 10ETH。
    目前的钱包合约状态为:
此时钱包合约地址总余额:20ETH
        
其中,登记为「钱袋1」的余额:10ETH
登记为「钱袋2」的余额:10ETH
// 钱袋1:属于「小A」与「小B」
// 钱袋2:属于「攻击合约」与「黑客X」
  1. 「黑客X」调用攻击合约的攻击函数。攻击代码段如下,注意,此函数位于「攻击合约」内:
function attack(address victim) {
    // victim 为被攻击的钱包合约地址
    PaymentSharer x = PaymentSharer(victim);
    // 继承钱包合约的各个函数
    x.updateSplit(2, 100);
    // 子步骤 1:钱袋2的「分账比」设置为「攻击合约」获取 100%
    x.splitFunds(2);
    // 子步骤 2:清算 钱袋2 的余额
    // 攻击达成:「攻击合约」与「黑客X」各获得 10ETH
  }

目前的钱包合约状态为:

此时钱包合约地址总余额:0ETH【他人余额被异常提取】
        
其中,登记为「钱袋1」的余额:10ETH
【此为账簿数组中的记账参数,非真实余额,目前已被黑客侵吞,无法实际兑付】
登记为「钱袋2」的余额:0ETH
// 钱袋1:属于「小A」与「小B」
// 钱袋2:属于「攻击合约」与「黑客X」

充值 10ETH,提现 20ETH,Happy~

。。。。。。
。。。。。
。。。。
。。。
。。

等等。。。啥玩意儿?这就攻击达成了???你啥都没解释啊!!!
别急,我们这就来拆解攻击逻辑:)

攻击逻辑拆解图

由于涉及合约间交互,做个一图流:

攻击拆解

按照标号逐步看,也可以结合代码。因该写的比较通俗了。

关键点:上图[流程 3]与[流程 6]的两次转账 transfer() 间,直接默认 “不会发生分账系数的变化” ,没有额外的状态检查。结果被人利用合约漏洞,插入[流程 3-4]后重入,实现了记账总额 200% 的异常提款。

可能还有同学有疑问,为什么 sstore 的 Gas 消耗 5000 时(以太坊现行逻辑)就没出过问题?代码不是一样么,也跑的通啊。

这里还有个额外的知识点,为了让转账函数 transfer() 更具扩展性,交易内额外触发的 transfer() 操作,默认会带上 2300 Gas 的“零钱”处理 fallback 中可能存在的后续操作(拆解图中的 3*)。

以太坊现行逻辑中,单次 sstore 消耗 5000 Gas,“零钱”根本不够扣。合约逻辑虽然不严密,但系统的资源限制事实上给大家兜了底。
君士坦丁堡更新,会令特殊条件下的 sstore 消耗大幅降低到 1700 Gas 的“可能性阈值”以下(用 call 触发还需要消耗 600 Gas),兜底已经失效,变成了真正的攻击入口。

总结

这是以太坊核心层的漏洞么?
我并不这么认为,作为合约的编写者,需要应对的是各种复杂而晦涩的逻辑陷阱。这一漏洞应当在合约编写时就有所防范,做好异常处理,而不是寄希望于“一个预置参数肯定不会变化,所以某些事情不用考虑,绝不可能发生”、“别人都这么做,所以我就 Ctrl-CV 一套”。

这是以太坊核心开发者的过错么?
sstore 的 Gas 计算调整早在 2018 年 8 月 1 日便列入了协议改进提案(EIP-1283),于 11 月被接受为正式改进,如此大幅降低消耗至 1700 Gas 可触发阈值以下的调整,理应更慎重的考虑旧合约的兼容性、安全性。

“无法篡改的技术负债”、“永远的前向兼容”。So good. So bad.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容