火星链 火星链
Ctrl+D收藏火星链
首页 > TRX > 正文

ESI:深入理解「拒绝服务」漏洞

作者:

时间:1900/1/1 0:00:00

1.前言

拒绝服务(DoS):DoS是DenialofService的简称,即拒绝服务,任何对服务的干涉,使得其可用性降低或者失去可用性均称为拒绝服务。简单的理解就是,用户所需要的正常服务请求无法被系统处理。例如一个计算机系统崩溃或其带宽耗尽或其硬盘被填满,导致其不能提供正常的服务,就构成拒绝服务。

拒绝服务攻击:造成DoS的攻击行为被称为DoS攻击,其目的是使计算机或网络无法提供正常的服务。

在互联网中,拒绝服务攻击大致可以分为三类:利用软件实现上的缺陷;利用协议上的漏洞;利用资源压制。而在区块链中,拒绝服务攻击扰乱、中止、冻结正常合约的执行,甚至合约本身的逻辑无法正常运行。

2.漏洞概述

在Solidity里,拒绝服务漏洞可以简单的理解为「不可恢复的恶意操作或者可控制的无限资源消耗」,也就是对以太坊合约进行DoS攻击,这就可能导致Ether和Gas的大量消耗,更严重的是让原本的合约代码逻辑无法正常运行。

举个例子,超市有三个收银点,正常来说人们排队在收银点进行扫码支付,但是有一天网络出现了问题,所有收银点的顾客扫码支付都失败了,而后面的人也不能进行支付买单,就导致了收银点的堵塞,超市不能正常运营。又或者,在支付时有顾客故意闹事,使得后面的顾客也不能去支付,这同样也会导致超市不能运营。我们可以看到有来自内部的,还有来自外部的,都是可能会造成拒绝服务攻击。

在智能合约中也是一样的,攻击者通过消耗合约的资源,让用户短暂地退出不可以操作的合约,严重时甚至能永久地退出,从而把以太币锁在被攻击的合约中。

3.漏洞分析

智能合约中的拒绝服务攻击一般有三种:

在外部操纵映射或数组循环。

马克·库班称自己已经完全改变看法 正在深入研究加密货币:6月21日消息,达拉斯独行侠队老板、亿万富翁马克·库班称自己正在深入研究加密货币,已经完全转变看法,不会错过这个。(bitcoin.com)[2021/6/21 23:52:57]

所有者操作。

基于外部调用的进展状态。

3

}

在上面的代码片段中我们可以看到,distribute()函数中会去遍历投资者数组,但是合约的循环遍历数组是可以被外部的人进行人为扩充,如果有攻击者要攻击这个合约,那么他可以创建多个账户加入投资者的数组,让investors的数据变得很大,大到让循环遍历数组所需的gas数量超过区块gas数量的上限,此时distribute()函数将无法正常操作,这样就会造成该合约的拒绝服务攻击。

针对以上情况,合约不应该对可以被外部用户人为操纵的映射或循环数组进行批量操作,这里更建议使用取回模式而不是发送模式,即每个投资者可以通过使用withdrawFunds()取回自己应得的代币。如果合约必须需要通过遍历一个变长数组来进行转账,那么最好是估计完成它们大概需要多少个区块以及多少笔交易,从而限制数组长度,此外还必须能够追踪得到当前进行到哪以便当操作失败时从那里开始进行恢复。如下面的代码所示,必须确保在下一次执行payOut()之前另一些正在执行的交易不会发生任何错误。

struct?Payee?{??address?addr;??uint256?value;}Payee?payees;uint256?nextPayeeIndex;function?payOut(){uint256?i?=?nextPayeeIndex;??while?(i?<?payees

姚前:区块链技术值得数据跨境流动及其监管各方深入研究:《中国金融》2020年第22期,中国证监会科技监管局局长姚前刊文《数据跨境流动的制度建设与技术支撑》表示,支付标记化技术将个人数据的“匿名化”交由可信第三方负责,而区块链技术则创造了用户完全自主可控的数据隐私保护新思路。用户的私钥可以本地生成,通过公钥计算发布有效的账户地址,从而隔断账户地址和账户持有人真实身份的关联。通过控制私钥,用户可以在区块链上自主完成交易,虽然在区块链网络上能够看到每一笔交易的细节,但无法对应到现实世界中的具体某个人。区块链技术从根本上打破中心化模式下数据控制者对数据的天然垄断,赋予用户真正的数据隐私保护权。区块链技术还可与先进密码学技术结合,发展出各类隐私保护方案。比如,利用基于环签名、群签名等密码学方案保护签名方身份;采用高效的同态加密方案实现密文的多方处理,隐藏用户交易金额等敏感信息;采用零知识证明方案,使交易数据能被审查和验证,但又不能被真实探知。区块链技术这一自主可控的隐私保护新思路,值得数据跨境流动及其监管各方深入研究。[2020/11/24 21:56:04]

3

//...额外的一些ICO功能//重写transfer函数,先检查isFinalizedfunctiontransfer(address_to,uint_value)returns(bool){?require(isFinalized);?super

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();?}}

声音 | 张平文:区块链等已经深入到市民生活的方方面面:月10日至11日,2019世界计算机大会在湖南长沙举行,中国科学院院士张平文说,计算机包括5G、云计算、大数据、人工智能、区块链等,已经深入到市民生活的方方面面。[2019/9/15]

攻击者先通过攻击合约调用bid()函数向竞拍合约转账成为新的竞拍者currentLeader,然后新的bid()函数被执行进行竞标的时候,当执行到require(currentLeader.send(highestBid))退还以太币操作时,会因为攻击合约的fallback()回退函数执行revert()而无法接收以太币,导致一直为false,其他竞拍者竞拍都会失败,最后攻击合约以较低的以太币赢得竞拍。

针对以上情况,如果需要对外部函数调用的结果进行处理后才能进入新的状态,那么一定要考虑外部调用可能一直失败的情况,也可以添加基于时间的操作,防止外部函数调用一直失败无法满足require判断。

4.相关案例

4.1演示案例

接下来会对拒绝服务攻击做出详细的演示讲解,以及会附上一个实例进行说明。

下面的合约代码是根据漏洞分析中第三点基于外部调用的进展状态讲的合约改的,正常的操作逻辑是任何出价高于当前合约price的都能成为新的president,合约中存款也会通过transfer()函数转账以太币退还给上一个president,这么看的话是没有任何问题的,但是以太坊是有两种账户类型,外部账户和合约账户,如果发起becomePresident()调用的是外部账户那就是正常的操作,但如果发起becomePresident()调用的是合约账户,并且在合约账户的fallback()函数中恶意的使用revert()等报错的函数,那么其他用户在发起becomePresident()时退还以太币给合约账户时会触发fallback()函数而导致报错,无法再正常进行becomePresident()中的逻辑成为新的president了。

动态 | 区块链等技术在物流、营销、质量追溯等领域应用日趋深入:前瞻产业研究院发布《中国零售行业市场前瞻与投资战略规划分析报告》,其显示,近年来,随着电商环境、技术平台和网购习惯的普及与完善,中国的零售业发生了翻天覆地的变化。例如,各大电商平台的线下门店落地,与传统零售商联盟化趋势加强,将线上线下资源进一步整合;人工智能、大数据、区块链等技术在物流、营销、质量追溯等领域应用日趋深入;电商流量加速分化,拼购模式、小程序电商、内容电商等新模式交易规模呈指数增长。[2019/5/10]

那么我们先来看下存在问题的合约代码,这里我们将合约代码设置为PresidentOfCountry.sol:

pragma?solidity?^0.4.19;contract?PresidentOfCountry?{??address?public?president;?//总统地址??uint256?price;?//出价??function?PresidentOfCountry(uint256?_price){?//构造函数,设置初始的价格????require(_price?>?0);????price?=?_price;?//设置初始的价格?}??function?becomePresident()?payable?{?//竞争总统????require(msg.value?>?price);?//支付的以太币必须大于当前总统的竞争费????president.transfer(price);??//退还以太币给上一任总统????president?=?msg.sender;???//设置新的总统为竞争成功用户????price?=?price;??????//设置最新的竞争价格?}}

在编写攻击合约之前,我们先来介绍下智能合约的两种账户类型以及fallback函数。

动态 | 北大光华成立金融科技联合实验室 向区块链等五大领域深入研究:10月12日,北京大学光华管理学院与度小满金融宣布合作成立金融科技联合实验室,并在北京大学为实验室揭牌。联合实验室主任刘晓蕾表示实验室将围绕数字化资产配置、超大规模关联网络、在线机器人、监管科技、区块链技术等五大领域深入研究,积极探索前沿技术在金融场景中的应用,同时推动跨学科人才的培养和输出。[2018/10/12]

以太坊中有两种账户类型:

外部账户,也就是用户账户,由私钥控制。

合约账户,可执行代码和私有状态,由合约代码控制。

回退函数(fallbackfunction):回退函数是每个合约中有且仅有一个没有名字的函数,并且该函数无参数,无返回值,如下所示:

function()publicpayable{...}

回退函数在以下几种情况中被执行:

调用合约时没有匹配到任何一个函数;

没有传数据;

智能合约收到以太币。

下面就来编写攻击合约,主要有两个重点,一个是外部调用becomePresident,二个就是在回退函数中使用revert。

pragma?solidity?^0.4.19;import?"./PresidentOfCountry.sol";contract?Attack?{??function?Attack(address?_target)?payable?{?//构造函数,设置目标合约地址,用call进行外部调用becomePresident????_target.call.value(msg.value)(bytes4(keccak256("becomePresident()")));?}??function?()?payable?{?//回退函数,使用revert报错???revert();?}}

在Remix中进行调试查看结果,首先使用账户(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4)设置初始竞争价格并部署漏洞合约代码PresidentOfCountry.sol。

部署好后合约的地址为0xd9145CCE52D386f254917e481eB44e9943F39138,后面在部署攻击合约时需要用到。

点击president可以查看当前竞争者的地址。

使用账户(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4)调用becomePresident并携带1eth,执行成功后再点击president查看,发现新的总统地址已经变成了0X5B的账户。

此时有一个攻击者(0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2)编写了一个攻击者合约Attack.sol,携带2eth并设置_target为PresidentOfCountry合约地址(0xd9145CCE52D386f254917e481eB44e9943F39138)进行部署。

部署好后的攻击合约地址为0xa131AD247055FD2e2aA8b156A11bdEc81b9eAD95,此时再点击president进行查看新总统的地址,发现已经是攻击合约的地址了。

之后如果还有其他用户想来竞争总统位置,就需要大于2eth的价格去调用becomePresident函数,这里有个用户(0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c)想去竞争总统,携带3eth去调用becomePresident,结果发现报错并回退,点击president发现总统地址还是攻击合约没,此时不管是谁使用多少的以太币去调用becomePresident,结果都是失败,该合约已经不能进行正常的操作,这就说明合约受到了拒绝服务攻击。

4.2真实案例

下列代码是实际合约中存在拒绝服务攻击的案例,只写了关键的代码并做了相关的改动。

可以看到合约的关键代码是用作提款操作,但是在提款中有一个判断要提款的金额和用户在该合约中存款的数量是否相等,而并不是大于等于,那么就有可能发生当用户要提出amount数量的代币时,由于各种原因导致balances变动,甚至是用户不想全部提款,从而使得判断条件require(balances==amount);不成立,这时就会造成短暂的拒绝服务攻击。

...functionwithdraw(uint256amount)public{//提款amount数量require(balances==amount);//检查要提款的金额是否等于该用户在合约中的存款?balances-=amount;//修改合约中存款的状态变量?msg.sender.transfer(amount);//转账到用户账户}

而修改的办法就是将判断条件require(balances==amount);修改为require(balances>=amount);就可以了。

4.3历史案例

在历史上,2016年2月6日至8日,在游戏KotET(KingogtheEtherThrone)的「TurbulentAge」期间,就遭受到了拒绝服务攻击,导致部分角色的补偿和未接收款项无法退回玩家的钱包中。

同年6月,GovernMental合约也遭受到了拒绝服务攻击,当时1100个以太币通过使用250万个gas交易而获得,这笔交易超出了合约能负荷的gas上限,从而导致交易暂停。

相关的还有Fomo3D等的拒绝服务攻击。

5.解决办法

通过上面的讲解,我们可以发现拒绝服务攻击在智能合约中的影响也是非常严重的,所以针对拒绝服务攻击,合约开发者应该针对上面漏洞分析时讲到的三种情况进行相应的代码修改。

比如对于外部操作的映射或者数组循环,需要对长度进行限制等;而对于所有者操作需要考虑合约的非唯一性,不要使得合约因为某个权限账户而导致整个业务瘫痪;基于外部调用的进展状态需要对函数的调用进行异常处理,一般来说内部函数的调用不会造成危害。

如果调用失败也只是会进行回退,而外部调用具有不确定性,我们不知道外部调用者想干什么,如果被攻击者攻击,就可能会造成严重的后果,具体表现为恶意返回执行错误,造成正常代码无法执行,从而造成拒绝服务攻击,那么针对这种开发者就应该加入函数执行异常的处理机制。

总的来说,合约开发者需要考虑合约代码的代码逻辑全面性和缜密性等,这样才能更好的杜绝拒绝服务攻击。

6.参考文献

拒绝服务攻击_百度百科(baidu.com)

以太坊智能合约安全入门了解一下(rickgray.me)

《智能合约安全分析和审计指南》

标签:RESENTESIDENTEMP SharesFootball DecentralizedGenesis NFTPRESIDENTDOGE价格

TRX热门资讯
GATE:Gate.io 首发上线Startup项目Mobius(MOT)及免费认购规则公告(免费瓜分120,000个MOT)

关于Gate.ioStartup免费空投计划为回馈平台用户,Gate.io上线“免费空投计划”,在Startup区不定期进行区块链项目的免费空投计划.

1900/1/1 0:00:00
SHB:一文简析捕获Synthetix MEV的详细过程

来源|?bertcmiller请看由EmGithub提供的rawsAssetsOracle请看由EmGithub提供的rawdYdXLiquidator.

1900/1/1 0:00:00
ULT:Multicoin Capital?:详解 DeFi 代币捕获价值能力的新框架

原文:MulticoinCapital作者:SpencerApplebaum这篇文章是《Layers1和Layer2的价值捕获》的续作。它也建立在《分叉DeFi协议》的一些想法之上.

1900/1/1 0:00:00
USDT:Gate.io 第八期云算力产品即将上线,静态年化收益高达70%

Gate.io第八期云算力产品将于今日上线,静态年化收益高达70%。无需购买矿机,您就可以通过挖矿获得数字货币.

1900/1/1 0:00:00
TRI:TWFI(Trister's Lend)

项目简介:TristerWorld起源于Trister爱好者社区,是由全球顶级加密科学家团队共同打造的?个以“价值创造、价值流通、价值驱动”且具有颠覆性的DeFi?融聚合平台.

1900/1/1 0:00:00
SQUA:Square签署旨在防止加密公司因专利相互起诉的协议

据Livebitcoinnews消息,支付公司Square正在加入一项针对加密货币的互不侵犯协议,该协议旨在减少针对加密和区块链公司的专利诉讼,并将数字货币世界推向主流领域.

1900/1/1 0:00:00