SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃


SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃

原文链接(英文版)
a SUI Move VM DoS vulnerability

漏洞描述
在SUI Move虚拟机模块里面,有一个未被mainnet-v1.2.1的完全修复的漏洞。在SUI Move虚拟机源码的TypeLayoutBuilder里面,有一个由递归函数调用导致的拒绝服务漏洞,该漏洞通过栈溢出导致fullnode崩溃。

该漏洞对testnet_v1.3.0有效

简介
递归函数调用的时候,如果没有限制调用深度,会导致栈溢出或者cpu、内存等资源的耗尽

细节
在SUI mainet v1.2.1里面,已经修复了导致validator崩溃的漏洞。但是没有修复能导致full-node溃的漏洞。在full-node的json-rpc-api里面,暴漏了一个”suix_getDynamicFieldObject”的接口。这个接口里面会调用move-bytecode-utils模块里面的TypeLayoutBuilder,TypeLayoutBuilder没有对结构体嵌套的深度做限制。

SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃


SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃

SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃

在SUI move里面,开发者可以在module里面声明struct。struct内部嵌套本module的其他struct、其他package的struct、其他module的struct。我们现在考虑一种攻击方式:定义一个struct A,然后A嵌套struct B,然后B嵌套struct C….这样一直嵌套下去,如果SUI move虚拟机是用一个递归函数来处理这种嵌套关系,那么SUI move虚拟机会因为栈溢出或者资源不足而崩溃。

通过测试,我们发现一个module里面可以定义199个有链式嵌套关系的struct。但是我们可以publish无数个module。

这样我们就有了攻击思路:

1.生成25个(完全可以比25多)package,每个package包含1个module

2.每个module里面定义199个有链式嵌套关系的struct,每个module里的第一个struct,嵌套上一个module里面的最后一个struct。

3.按照顺序publish每个package

4.按照顺序用json-rpc-api调用”suix_getDynamicFieldObject”,查询某个object的第199个结构体。这个object的id可以写成任意合法或非法的值
curl --location --request POST 'http://127.0.0.1:9000' --header 'Content-Type: application/json' --data-raw '{  "jsonrpc": "2.0",  "id": 1,  "method": "suix_getDynamicFieldObject",  "params": [    "0xc8359b6b5e3bfeab524e5edaad3a204b4053745b2d45d1f00cd8d24e5b697607",    {      "type": "package_id::hello::T_198",      "value": "xyz"    }  ]}'


5.full-node会在某个时间点因为栈溢出而崩溃

SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃


漏洞补丁:
SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃


可以看到,补丁代码限制了递归调用的深度。

影响
mainnet分支的v1.0.0、v1.1.0、v1.1.1、v1.2.1,testnet分支的v1.0.0、v1.1.0、v1.1.1、v1.2.0、v1.3.0,都有此漏洞

风险
这个漏洞利用非常简单,一次攻击只需要消耗相当于发布6个(有时候会多一点)左右合约的gas

根据immunefi-vulnerability-severity-classification-system-v2-2,我们将其严重等级划分为High

建议
在处理一个结构体引用另外一个结构体的时候,对相关递归函数的深度做限制

相关引用
https://github.com/MystenLabs/sui/tree/mainnet/external-crates/move

漏洞补丁:  
https://github.com/MystenLabs/sui/commit/fe8eb7e1fa647545e5b356796c826c1670e61d08

Proof of Concept
SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃


构造本地mainnet网络
1.准备4个ubuntu机器

2.4个ubuntu机器都要安装mainnet的sui和sui-node

3.在某个ubuntu机器里面,运行以下命令

    sui genesis –benchmark-ips 192.168.15.130  192.168.15.131  192.168.15.132  192.168.15.133

    参数里面的ip地址可以修改为你自己的4个机器的地址

4.将生成的~/.sui/sui_config/文件夹复制到其他3个机器上

5.每个机器都运行如下命令,启动validator

    sui-node –config-path ~/.sui/sui_config/validator-config-0.yaml

    其中的0表示机器编号,每个机器都不一样

6.在某个机器里面,运行以下命令,启动一个全节点

    sui-node –config-path ~/.sui/sui_config/fullnode.yaml

7.~/.sui/sui_config/benchmark.keystore对应一个address,这个address里面已经有了一定的资金。我们可以在client.yaml里面指向这个地址

poc运行环境
1.ubuntu

2.安装sui,并将sui添加到Path环境变量。同时要配置sui的client.yaml,使其有一个address,address里面有足够的SUI(10 SUI完全够用)

3.将附件里面的hello-world_xxxxx文件夹、test文件夹、script.py文件,复制到~/Desktop

4.运行~/Desktop/script.py

5.在很短一段时间后,我们将看到fullnode会崩溃

6.在~/Desktop/test文件夹里面,我们将看到我们批量生成的sui package

推荐阅读
项目案例

原文始发于微信公众号(共码信安):SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃

版权声明:admin 发表于 2023年10月11日 上午6:24。
转载请注明:SUI公链Move虚拟机模块的栈溢出漏洞导致全节点崩溃 | CTF导航

相关文章