DreamHack/Web hacking

[LEVEL-1] session-basic

쿼딩~ 2023. 11. 20. 14:15
#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for

app = Flask(__name__)

try:
    FLAG = open('./flag.txt', 'r').read()
except:
    FLAG = '[**FLAG**]'

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


# this is our session storage
session_storage = {
}


@app.route('/')
def index():
    session_id = request.cookies.get('sessionid', None)
    try:
        # get username from session_storage
        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"}')


@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:
            # you cannot know admin's pw
            pw = users[username]
        except:
            return '<script>alert("not found user");history.go(-1);</script>'
        if pw == password:
            resp = make_response(redirect(url_for('index')) )
            session_id = os.urandom(32).hex()
            session_storage[session_id] = username
            resp.set_cookie('sessionid', session_id)
            return resp
        return '<script>alert("wrong password");history.go(-1);</script>'


@app.route('/admin')
def admin():
    # developer's note: review below commented code and uncomment it (TODO)

    #session_id = request.cookies.get('sessionid', None)
    #username = session_storage[session_id]
    #if username != 'admin':
    #    return render_template('index.html')

    return session_storage


if __name__ == '__main__':
    import os
    # create admin sessionid and save it to our storage
    # and also you cannot reveal admin's sesseionid by brute forcing!!! haha
    session_storage[os.urandom(32).hex()] = 'admin'
    print(session_storage)
    app.run(host='0.0.0.0', port=8000)

코드를 읽어보면

‘guest’와 ‘user’의 아이디와 비밀번호는 알려주었으므로, 우선 ‘user’ 계정으로 들어가서 세션id를 보려고 했다.

이렇게 나온 것을 볼 수 있는데

세션id는

→ session_id = os.urandom(32).hex() 이 코드를 통해

64개의 16진수 문자를 갖게 됩니다(32바이트 * 2)

 

그렇다면 어드민의 세션 아이디는 무작위 대입을 쓰지 않고는 찾기 힘들겠다는 생각을 하고 다른 방법을 찾던 찰나

/login이 문자열은 ‘Login’ form을 들어갈 때 url 뒤에 붙는 문자열이었던 것.

 

그렇다면?

@app.route('/admin')
def admin():
    # developer's note: review below commented code and uncomment it (TODO)

    #session_id = request.cookies.get('sessionid', None)
    #username = session_storage[session_id]
    #if username != 'admin':
    #    return render_template('index.html')

    return session_storage

이 코드를 보아 /admin에도 무언가가 있던지, 어드민 로그인에 관련된 정보가 있던지 할 것이라 생각하고 url뒤에 ‘/admin’ 문자열을 삽입해봤더니???????

어드민의 세션ID 값과 user의 세션ID 값이 나오게 되었다.

 

그렇다면 user의 계정으로 로그인 한 후 세션 ID 값을 어드민의 세션 값으로 바꾸어주면????????

FLAG가 출력되었다.

 

해결~~~!!~!~~@~@~#~@~#~@