728x90
https://dreamhack.io/wargame/challenges/566
이 문제를 풀며, flask에서 제공하는 session 구조에 대해 정리해보겠다.
from flask import Flask, request, redirect, url_for, render_template, session
import os
app = Flask(__name__)
app.secret_key = 'your_secret_key_here'
# 간단한 사용자 데이터베이스를 대신할 딕셔너리
users = {'user1': 'password1', 'admin': 'admin'}
@app.route('/')
def home():
if not session.get('logged_in'):
return redirect(url_for('login'))
else:
return '로그인 성공! 홈페이지 내용'
@app.route('/login', methods=['GET', 'POST'])
def login():
# 로그인 시도 카운트를 세션에서 가져오거나 초기값 설정
session['login_attempts'] = session.get('login_attempts', 0) + 1
session['id'] = os.urandom(16)
print(session['id'])
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if username in users and users[username] == password:
session['logged_in'] = True
session['login_attempts'] = 0 # 로그인 성공시 시도 횟수 초기화
return redirect(url_for('home'))
else:
return render_template('login.html', message='로그인 실패! 다시 시도하세요.', attempts=session['login_attempts'])
# GET 요청시 로그인 폼 렌더링, 실패 횟수도 함께 전달
return render_template('login.html', attempts=session['login_attempts'])
if __name__ == '__main__':
app.run(debug=True)
app.py
<!DOCTYPE html>
<html>
<head>
<title>로그인 페이지</title>
</head>
<body>
<h2>로그인</h2>
{% if message %}
<p>{{ message }}</p>
{% endif %}
<p>로그인 시도 횟수: {{ attempts }}</p>
<form method="post">
사용자 이름: <input type="text" name="username"><br>
비밀번호: <input type="password" name="password"><br>
<input type="submit" value="로그인">
</form>
</body>
</html>
templates/login.html
간단하게 실습해볼 수 있는 코드다.
접속하면 볼 수 있는 session의 값이다. 자세히 보면 두 개의 `.`으로 구분되어 있다. 마치 jwt와 같이 말이다.
실제로 base64로 인코딩 되어 있는 구조라서 jwt 디코딩 사이트에서 디코딩이 가능하다.
각각 데이터 부분, 타임 스탬프 부분, 서명 부분으로 나눌 수 있다. 서명 부분은 세션이 수정되지 않았다는 것을 증명하기위해 쓰이며, ` itsdangerous `라이브러리와 서버에서 설정한 secret 키를 이용해 직렬화와 서명을 수행한다.
여기서 id 부분에 객체로 값이 들어가는 것을 볼 수 있는데, `session['id'] = os.urandom(16)`의 결과로 보인다. 한 번 실행해서 확인해보자.
바이너리 들어가면서 위와 같이 형태가 변형된 것으로 보인다. 자세한 내용은 더 찾아봐야 할 것 같다.
flask-session은 flask에서 제공하는 session을 커스터마이징할 수 있는 기능을 제공한다고 한다.
728x90
반응형
'분류 전 > 개념 노트장' 카테고리의 다른 글
Reverse Shell 실습 (0) | 2024.07.09 |
---|---|
Interval이 다를 때 OTP 코드가 다른 이유와 드림핵 SuperSecure OTP (0) | 2024.07.07 |
[SQL] information_schema가 필터링 됐을 때 Union SQL Injection (0) | 2024.03.29 |
[Node.js] prepared statement 사용 시 주의 사항 (1) | 2024.03.28 |
[SQL] mysql boolean 비교 시 동작 방식과 false injection (0) | 2024.02.23 |