前言:本文由五个章节组成,分别是Parity相关介绍、UTF-8编码是什么、Rust危险的字符串切片、漏洞分析、修复方案和总结。今天我们将由浅入深地为各位读者展示以太坊的parity客户端全版本远程DoS漏洞分析。
以太坊Parity客户端是除Geth之外使用量最高的一款以太坊客户端,使用的是Rust语言。
根据ethernodes最新数据显示:以太坊parity客户端在整个以太坊网络中占30%,Geth客户端占40%。
在今年2月3日时,这款客户端官方发表公告称修复了一个远程拒绝服务的严重漏洞,这个漏洞影响2.2.9之前的版本和2.3.2-beta之前的版本,而2.2.9和2.3.2-beta已经是最新版。从官方的通告来看,可理解为:目前这个漏洞通杀漏洞修复前的所有版本。
虽然该漏洞影响版本很多,但影响范围有限。原因便是该漏洞需要攻击者能够访问目标Parity客户端的JSONRPC,而Parity默认是不对外开放JSONRPC端口。
该漏洞具体影响范围可以通过FOFA统计出结果:
从上图,我们可以看到目前公网上有1195个parity节点开放了JSONRPC端口,故该漏洞影响版本多,但影响范围有限。
我们在研究这个漏洞之前需要了解一下UTF-8编码,来帮助我们更好为漏洞研究做准备。
Unicode是一种字符编码,是目前计算机行业内比较通用的一个编码,因为Unicode把所有语言都统一到一套编码里,解决了行业内由于语言不一致而导致的乱码问题。
而UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,又称万国码。
在这篇漏洞分析中,你只需要知道以下知识点就够了:
UTF-8编码中,一个英文字符占一个字节,一个中文(含繁体)占三个字节。
在上个章节中介绍了UTF-8编码的原因是:Rust就是使用的UTF-8编码,以太坊Parity客户端使用的编程语言是Rust。
字符串切片很好理解,就是截取出字符串中的某一段字符串,不过Rust的字符串切片有一个毛病:
切的是字节,不是字符
笔者简单来测试一下,如下图:
通过图片内容显示,我们可以看到当切片str1字符串的0-3个元素的时候,切出来了”DVP”3个字符,但是当切片3-6个元素的时候,如果按字符切的话应该切出来“是最棒”,但是并没有。
为什么会出现这种情况?
原因是Rust按字节切片。在文章此部分之前提到过:在UTF-8中英文占1个字节,中文占3个字节,所以我们切3-6就只切出来了“是”这一个字。
这是正好3个字节切片切到了一个完整中文字符的情况。设想一下:假如切片切的是2个字节呢?
— 会显示半个中文吗?
— 答案是:当然不会了。
当切片切出来不是一个完整字符的时候,Rust不会给你切出来任何字符,而是报错。
简单测试一下
通过图片我们可以看到,当切片3-5的时候程序报错了,因为切到的不是一个完整的中文字符。
以太坊Parity客户端正是犯了这个错误,这也是我们今天本文中漏洞分析的关键所在。
DVP安全团队在编写本文时,官网没有披露任何漏洞详情,可能是因为一些节点还未更新到新版修复漏洞的缘故,而且检索一番之后发现网络上也没见到有人在讨论这个漏洞,于是只能去Parity的github中翻查commit记录,试图找到关于这个漏洞的修复补丁,通过补丁来分析漏洞,最终我们看到了这个commit:
https://github.com/paritytech/parity-ethereum/commit/3b23c2e86d09a8a8b8cd99dfa02390177498e6b7
大概看了一下,基本可以确认这就是修复补丁了,补丁中多处把字符串切片换成了starts_with函数:
通过上图,可以看到,在之前的写法中是先把字符串的0至2个元素切出来,并判断是不是以”0x”开头,如果长度小于2并且前两个元素的字符串不是”0x”的话就返回一个error.本文上面我们了解了Rust的切片是存在一定危险性的,如果被切片的字符串可控的话就会导致程序报错。
那么,这些使用了字符串切片的地方是否能被远程利用呢?
仔细看图可以发现,图中被修改的两个文件都在rpc目录的types目录下,我们猜测应该是为JSONRPC接口传来的数据定义的一些类型,图中就有hash和uint。
再去翻查以下官方的RPC文档:.
原来官方文档其实都有说明,由于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
往期DVP漏洞文章精彩集锦:
●DVP漏洞分析|某交易所框架存在严重逻辑漏洞,可重置任意用户密码!
●POSCMS交易所系统多个高危漏洞详解,可前台GetShell!
● DVP漏洞专题|交易所安全之殇,中小问题能够引起大危害?
● DVP漏洞专题|公链安全之比特币任意盗币漏洞浅析(CVE-2010-5141)
● 诈骗疯狂敛财!币安刚发布推出去中心化交易平台新闻,就有人仿冒!?
(扫码加入微信社群)
长按二维码
就可以关注公众号哦~