1. "use strict";
    2. var randomstring = require("randomstring");
    3. var express = require("express");
    4. var {
    5. VM
    6. } = require("vm2");
    7. var fs = require("fs");
    8. var app = express();
    9. var flag = require("./config.js").flag
    10. app.get("/", function(req, res) {
    11. res.header("Content-Type", "text/plain");
    12. /* Orange is so kind so he put the flag here. But if you can guess correctly :P */
    13. eval("var flag_" + randomstring.generate(64) + " = \"flag{" + flag + "}\";")
    14. if (req.query.data && req.query.data.length <= 12) {
    15. var vm = new VM({
    16. timeout: 1000
    17. });
    18. console.log(req.query.data);
    19. res.send("eval ->" + vm.run(req.query.data));
    20. } else {
    21. res.send(fs.readFileSync(__filename).toString());
    22. }
    23. });
    24. app.listen(3000, function() {
    25. console.log("listening on port 3000!");
    26. });

    程序逻辑很简单,读取flag,存入随机名字的变量中。
    创建vm2沙箱,在沙箱中执行代码,并返回执行的结果。

    原本思路是沙箱逃逸,搜来搜去发现了另一个漏洞,和沙箱逃逸没啥关系。
    Node.js中存在一个对象Buffer,用于创建缓冲区,但是不同于TypedArray,在使用new Buffer(size)或者它的别名Buffer(size)创建时,会得到一块未被清空的内存,而这块内存包含之前的各种变量以及数据。

    那么接下来就可以通过这个对象来读取到flag变量。
    payload:

    1. http://111.200.241.244:48918/?data=Buffer(1e4)

    访问后会下载一个文件,在文件中搜索flag关键字即可拿到flag。