1. Hi区块链首页
  2. 资讯
  3. 竞争币

以太坊parity客户端全版本远程DoS漏洞分析

前言:本文由五个章节组成,分别是Parity相关介绍、UTF-8编码是什么、Rust危险的字符串切片、漏洞分析、修复方案和总结。今天我们将由浅入深地为各位读者展示以太坊的parity客户端全版本远程DoS漏洞分析。

...

前言:本文由五个章节组成,分别是Parity相关介绍、UTF-8编码是什么、Rust危险的字符串切片、漏洞分析、修复方案和总结。今天我们将由浅入深地为各位读者展示以太坊的parity客户端全版本远程DoS漏洞分析。

一、Parity相关介绍

 

以太坊Parity客户端是除Geth之外使用量最高的一款以太坊客户端,使用的是Rust语言。

根据ethernodes最新数据显示:以太坊parity客户端在整个以太坊网络中占30%,Geth客户端占40%。

图片1在今年2月3日时,这款客户端官方发表公告称修复了一个远程拒绝服务的严重漏洞,这个漏洞影响2.2.9之前的版本和2.3.2-beta之前的版本,而2.2.9和2.3.2-beta已经是最新版。从官方的通告来看,可理解为:目前这个漏洞通杀漏洞修复前的所有版本。

虽然该漏洞影响版本很多,但影响范围有限。原因便是该漏洞需要攻击者能够访问目标Parity客户端的JSONRPC,而Parity默认是不对外开放JSONRPC端口。

该漏洞具体影响范围可以通过FOFA统计出结果:

图片2从上图,我们可以看到目前公网上有1195个parity节点开放了JSONRPC端口,故该漏洞影响版本多,但影响范围有限。

二、UTF-8编码是什么?

 

我们在研究这个漏洞之前需要了解一下UTF-8编码,来帮助我们更好为漏洞研究做准备。

Unicode是一种字符编码,是目前计算机行业内比较通用的一个编码,因为Unicode把所有语言都统一到一套编码里,解决了行业内由于语言不一致而导致的乱码问题。

而UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,又称万国码。

在这篇漏洞分析中,你只需要知道以下知识点就够了:

UTF-8编码中,一个英文字符占一个字节,一个中文(含繁体)占三个字节。

 

三、Rust危险的字符串切片

 

在上个章节中介绍了UTF-8编码的原因是:Rust就是使用的UTF-8编码,以太坊Parity客户端使用的编程语言是Rust。

字符串切片很好理解,就是截取出字符串中的某一段字符串,不过Rust的字符串切片有一个毛病:

切的是字节,不是字符

笔者简单来测试一下,如下图:

图片3

通过图片内容显示,我们可以看到当切片str1字符串的0-3个元素的时候,切出来了”DVP”3个字符,但是当切片3-6个元素的时候,如果按字符切的话应该切出来“是最棒”,但是并没有。

为什么会出现这种情况?

原因是Rust按字节切片。在文章此部分之前提到过:在UTF-8中英文占1个字节,中文占3个字节,所以我们切3-6就只切出来了“是”这一个字。

这是正好3个字节切片切到了一个完整中文字符的情况。设想一下:假如切片切的是2个字节呢?

—  会显示半个中文吗?

—  答案是:当然不会了。

当切片切出来不是一个完整字符的时候,Rust不会给你切出来任何字符,而是报错。

简单测试一下

图片4通过图片我们可以看到,当切片3-5的时候程序报错了,因为切到的不是一个完整的中文字符。

以太坊Parity客户端正是犯了这个错误,这也是我们今天本文中漏洞分析的关键所在。

四、漏洞分析

 

DVP安全团队在编写本文时,官网没有披露任何漏洞详情,可能是因为一些节点还未更新到新版修复漏洞的缘故,而且检索一番之后发现网络上也没见到有人在讨论这个漏洞,于是只能去Parity的github中翻查commit记录,试图找到关于这个漏洞的修复补丁,通过补丁来分析漏洞,最终我们看到了这个commit:

https://github.com/paritytech/parity-ethereum/commit/3b23c2e86d09a8a8b8cd99dfa02390177498e6b7

大概看了一下,基本可以确认这就是修复补丁了,补丁中多处把字符串切片换成了starts_with函数:

图片5通过上图,可以看到,在之前的写法中是先把字符串的0至2个元素切出来,并判断是不是以”0x”开头,如果长度小于2并且前两个元素的字符串不是”0x”的话就返回一个error.本文上面我们了解了Rust的切片是存在一定危险性的,如果被切片的字符串可控的话就会导致程序报错。

那么,这些使用了字符串切片的地方是否能被远程利用呢?

仔细看图可以发现,图中被修改的两个文件都在rpc目录的types目录下,我们猜测应该是为JSONRPC接口传来的数据定义的一些类型,图中就有hash和uint。

再去翻查以下官方的RPC文档:.

图片6原来官方文档其实都有说明,由于json里面只有字符串和数值两个类型,所以像integers、byte、hashes这些数据类型都是通过以0x为前缀的字符串形式编码传输的。

根据官方文档的描述,我们测试漏洞就很方便了。在文档给的请求样例中任意找一个参数中有0x前缀的,省去了看函数调用链的时间。

这里找了一个比较常见的eth_getTransactionByHash接口,请求方式如下:

curl --data '{"method":"eth_getTransactionByHash","params":["交易hash"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545

利用的话也很简单,将”交易hash”替换为中文字符串就行了,例如:

curl --data '{"method":"eth_getTransactionByHash","params":["你好DVP"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545

实际演示一下:

替换

可以看到在请求接口后节点确实发生了异常并崩溃了。

 

五、修复方案和总结

 

官方的修复方案前面有提到,就是将字符串[a..b]这种切片写法全部修改掉。

不过这只是一时的修补方案,若想长久的预防此类漏洞,我们认为公链开发者应该要比传统软件开发者更了解语言的特性,因为很多代码用常规编程思维去看问题不大,但是语言本身可能存在一些开发者并不了解的特性,在特性的辅助下漏洞就产生了,之前就有公链使用go语言滥用make函数,而且参数控制不当,然后产生由OOM导致的拒绝服务漏洞。

故DVP安全团队通过本期漏洞分析希望能够借此给大家警示,区块链开发者在未来的开发之路上,需要更加了解语言的特性,这样才能让区块链生态更加稳固、安全。

参考链接

https://www.parity.io/security-alert-parity-ethereum-03-02/

https://blog.csdn.net/wowotuo/article/details/75579103

https://baike.baidu.com/item/UTF-8/481798?fr=aladdin

https://github.com/paritytech/parity-ethereum/commit/3b23c2e86d09a8a8b8cd99dfa02390177498e6b7

https://wiki.parity.io/JSONRPC

声明:登载此文出于传递更多信息之目的,观点仅代表作者本人,绝不代表Hi区块链赞同其观点或证实其描述。

提示:投资有风险,入市须谨慎。本资讯不作为投资理财建议。