0day-NEO智能合约平台Runtime.Notify调用拒绝服务漏洞
— 发现的第一个0day —
前言
在实验室改以太坊的智能合约到neo。
改着改着发现一个拒绝服务攻击漏洞,利用攻击的话整个链会全部崩掉,没法出块,危害还挺大的,emmm,在此记录第一个0day。
漏洞
漏洞名称:NEO智能合约平台Runtime.Notify()调用拒绝服务漏洞
漏洞影响:导致Neo链上所有开启log模式
的全节点崩溃(包括共识节点)。
漏洞细节:出现在neo全节点虚拟机中执行智能合约语句Runtime.Notify()时发生崩溃
Neo智能合约平台为合约提供了记录数据信息输出到文件的系统调用System.Runtime.Notify
。该调用在处理合约请求时未考虑到全部可能的数据结构,将导致智能合约系统平台crash。
其产生的影响会根据节点的部署情况而有所不同,但是都较为严重。
由于Neo目前是有7个主节点负责验证并打包全网交易。恶意用户将利用该漏洞的恶意合约发布到neo网络中,假如超过4个主节点开启了LOG功能,这些节点在解析运行该恶意合约时将引发崩溃,无法继续达成共识,进而导致整个neo网络拒绝服务。
即使主节点不使用LOG可以完成共识正常出块,但是NEO链中所有NEP5代币智能合约都会使用LOG功能,几乎所有DAPP也会使用LOG功能。所有LOG节点崩溃,会使基于NEO链的大部分智能合约瘫痪。
崩溃截图:
漏洞产生原因
在执行Runtime.Notify没有考虑所有可能被 Runtime.Notify 写入日志文件的数据类型,在数据转化时解析出错。
Runtime.Notify 是记录智能合约日志的功能,可以输出想要知道的数据的值。类似于console.log()
,输出的数据会写入LevevlDB数据库,最后变为一个文件。
判断是否是log模式
构建文件,写入文件
其中ToParameter函数
在转化Map格式时崩溃。
官方回复:因为ToParameter函数在实现的时候还没有Map,后来做了Map功能后忘记更新ToParameter了。
ToParameter函数,在官方github中的NEO项目中ContractParameter.cs
、ContractParameterType.cs
、Helper.cs
实现
漏洞攻击过程
攻击过程
:
- 构建恶意智能合约代码
- 部署智能合约
- 调用恶意智能合约
- 所有开启log功能的节点同步区块,执行智能合约代码,崩溃。(如果共识节点开启log功能,会直接崩溃,不会产生区块)
当时提交的智能合约POC分析:
(复杂版,当时没有去看源码觉得有两种漏洞原因,以为可能是跟360找到的漏洞一样,因为map与struct嵌套导致漏洞,也有可能是因为其中一种结构,没有排除到根本)
1 | using Neo.SmartContract.Framework; |
按照官方的原因的话,应该直接建立一个MAP结构,Runtime.Notify(MAP)格式,就可以,不用向上面那么复杂
贴上攻击结果的一些截图:
共识节点开启log:
共识节点不开启log:
漏洞修补
官方于09.10修补了漏洞,添加了map对应处理情况。修复情况链接
最后
很感谢学长和老师(就不贴出名字了)引入门的指导,一直以来的支持和照顾。这也是能发现0day不可或缺的先前条件。
信息安全就是如此,潜心学习,沉淀,耐心研究,挖掘,总有收获。
共勉。