【vm沙箱逃逸】

一、什么是沙箱


二、使用方式



我们想在沙箱里运行代码会报错

主要是因为这个是主环境里的原型,沙箱里没有这个对象

通俗来说this是外部传入的,通过this来获取外部环境的原型来获取到process


三、vm2


目前的逃逸已经有很多方法了

我们就用其中一个例子来分析


in操作符的查找机制

当执行 "" in proxy;时,JavaScript 引擎会检查字符串 ""是否是 proxy对象的一个属性(或其原型链上的属性)。这个过程在代理对象中的逻辑如下:

首先,引擎会查看创建 proxy时传入的 handler对象是否定义了 has陷阱。代码中handler只定义了 get陷阱,没有定义 has陷阱。

由于没有 has陷阱进行拦截,引擎会转向默认行为,即对 proxy所代理的目标对象 target(这里是 {})执行默认的 [[HasProperty]]内部操作。

默认的 [[HasProperty]]与原型链

\[HasProperty\]\]是一个内部操作,它的核心功能就是:判断一个对象(或其原型链上)是否拥有指定的属性。 当使用 in操作符(例如 "name" in obj)时,JavaScript 引擎在底层调用的就是这个 [\[HasProperty\]](P)内部方法,其中 P就是属性名 "name"。 对于普通对象 target(即 {}),in操作符(或内部的 \[\[HasProperty\]\])会沿着该对象的原型链向上查找属性。 target本身是空对象,没有 has方法。 接着,查找 target的原型,即 Object.getPrototypeOf(target),它指向 Object.prototype。 在代码中,通过 Object.prototype.has = function() { ... }在 Object.prototype上直接添加了一个 has方法。 因此,当查找 has属性时,就在 Object.prototype上找到了它,于是执行了这个方法,打印出了 "has"。 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/9b33dab8d85440dcad5ac38f0aa84936.png) Object.prototype.has = function (t,k) { process = t.constructor("ret,rn process")(); }; **原型污染:** 在 Object.prototype上定义 has方法。由于所有对象都继承自 Object.prototype,沙箱内外所有对象都能访问此方法。 关键点:当 has方法被调用时,参数 t会是外部的原始对象(后面解释如何触发)。 **利用构造函数逃逸:** t.constructor:获取 t的构造函数,即外部的 Function构造器。 "return process" 是创建一个返回外部 process对象的函数并立即执行。 执行结果(外部 process对象)赋值给沙箱内的 process变量。 "use strict"; 作用:启用 JavaScript 的严格模式,使代码在更严格的规则下运行。 在逃逸中的作用:确保代码行为可预测,避免某些静默错误干扰攻击流程。 var process; 作用:在沙箱内部声明一个 process变量(此时为 undefined)。 策略:为后续存储外部真正的 process对象预留变量名。沙箱通常会阻止直接访问 Node.js 的全局 process对象,因此需要间接获取。 核心攻击代码: Object.prototype.has = function (t,k) { process = t.constructor("ret,rn process")(); }; **原型污染:** 在 Object.prototype上定义 has方法。由于所有对象都继承自 Object.prototype,沙箱内外所有对象都能访问此方法。 关键点:当 has方法被调用时,参数 t会是外部的原始对象(后面解释如何触发)。 **利用构造函数逃逸:** t.constructor:获取 t的构造函数,即外部的 Function构造器。 代码中的 "ret,rn process"应该是 "return process"的笔误/混淆。实际效果是创建一个返回外部 process对象的函数并立即执行。 执行结果(外部 process对象)赋值给沙箱内的 process变量。 **触发机制:** "" in Buffer.from; **in操作符的工作流程:** 执行 "" in Buffer.from时,检查 Buffer.from是否包含空字符串属性。 由于 Buffer.from是 Proxy,且 handler没有 has陷阱,引擎执行默认行为。 默认行为:对 Buffer.from的目标对象(外部真正的 Buffer.from函数)调用 `[[HasProperty]]("")`。 **原型链查找触发污染方法:** 在查找属性过程中,引擎会沿着外部 Buffer.from的原型链查找。 外部 Buffer.from的原型链:Buffer.from→ Function.prototype→ Object.prototype。 由于 Object.prototype.has已被污染,在某些 JavaScript 引擎的实现中,属性检查可能会调用 has方法。 最关键的是:当 has方法被调用时,它的 this上下文或参数 t会是外部的 Buffer.from函数。 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ca0ee17d0c61433f9cc08a6438b1ec91.png) ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d7922f0e67ee4ddf8a47a7b66ec20264.png) ## 四、练习 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e2034efae9ad4846a11c105373e1f4be.png) (function(){ // 1. 污染 TypeError 的原型链 TypeError.prototype.get_process = f => f.constructor("return process")(); try { // 2. 故意触发一个 TypeError 异常 Object.preventExtensions(Buffer.from("")) = a = 1; } catch(e) { // 3. 利用捕获的异常对象执行逃逸 return e.get_process(() => {}).mainModule.require("child_process").execSync("whoami").toString(); } })() **原型链污染** TypeError.prototype.get_process = f => f.constructor("return process")(); 目标:污染 TypeError.prototype,为所有 TypeError实例添加 get_process方法。 方法原理:get_process方法接收一个函数 f,通过 f.constructor获取 Function构造函数,然后动态创建一个返回 process对象的函数并立即执行。 为什么有效:f.constructor总是返回 Function构造函数(除非 f的原型链被修改),而 Function构造函数在创建函数时默认使用当前执行上下文的全局对象。 **故意触发异常** Object.preventExtensions(Buffer.from("")) = a = 1; Object.preventExtensions()使对象不可扩展(不能添加新属性)。 对 Buffer.from("")的结果调用此方法后,尝试给返回值赋值 a = 1。 关键错误:在严格模式下,给不可写的属性或不可扩展的对象赋值会抛出 TypeError异常。 **利用异常对象逃逸** catch(e) { return e.get_process(() => {}).mainModule.require("child_process").execSync("whoami").toString(); } 捕获异常:e是 TypeError实例,因为前面污染了原型,所以它有 get_process方法。 获取 process:e.get_process(() =\> {})执行时: (() =\> {})是一个箭头函数,它的 constructor指向 Function f.constructor("return process")()在外部全局上下文中执行,返回外部真正的 process对象 执行命令:通过获取的 process对象执行 whoami命令。 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/bb8f3c1f73454d78a043cfbfa62812be.png) ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/03d2409827c84604975817d4e4aa0601.png)

相关推荐
belldeep7 小时前
nodejs: 能在线编辑 Markdown 文档的 Web 服务程序,更多扩展功能
前端·node.js·markdown·mermaid·highlight·katax
松树戈11 小时前
【vfox教程】一、vfox在win系统下的安装与卸载
jdk·node.js·vfox
x-cmd2 天前
[x-cmd] Node.js 的关键一步:原生运行 TypeScript 正式进入 Stable
javascript·typescript·node.js·x-cmd
盖头盖2 天前
【nodejs原型链污染】
node.js
御坂10101号2 天前
JIT 上的 JIT:Elysia JS 的优化实践与争议
开发语言·javascript·网络·性能优化·node.js·express
belldeep2 天前
nodejs: 能在线编辑 Markdown 文档的 Web 服务程序
node.js·markdown·mermaid
佛系快乐土2 天前
【AI角色扮演游戏平台】记录开发过程中遇见的问题
typescript·node.js
dc_00123 天前
最新最详细的配置Node.js环境教程
node.js
极客小云4 天前
【实时更新 | 2026年国内可用的npm镜像源/加速器配置大全(附测速方法)】
前端·npm·node.js