간단한 로그인이라 하지만 flag를 딴 사람은 2350명이다.
Cookie 문제는 10000명이 넘었는데
문제 화면이다.
admin으로 login 하는 거 같다.
코드를 한번 봐보자.
#!/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
}
session_storage = {
}
@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"}')
@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]
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(4).hex()
session_storage[session_id] = username
resp.set_cookie('sessionid', session_id)
return resp
return '<script>alert("wrong password");history.go(-1);</script>'
if __name__ == '__main__':
import os
session_storage[os.urandom(1).hex()] = 'admin'
print(session_storage)
app.run(host='0.0.0.0', port=8000)
사용자 정보를 저장하는 {users}를 보면 guest(ID) : guest(PW) , user : user1234 , admin : {FLAG}로 정의되어있는 걸 볼 수 있다.
이때 FLAG는 알 수 없으니 login 함수를 봐보자
계정명은 admin 확인되었으니 pw를 보면...
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]
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(4).hex()
session_storage[session_id] = username
resp.set_cookie('sessionid', session_id)
return resp
return '<script>alert("wrong password");history.go(-1);</script>'
로그인요청은 POST로 처리를 하고 username은 이미 admin으로 알고 있으니 try 은 넘어간다.
if pw == password: 를 보면 session_id에 대한 설정이 나온다.
'session_id = os.urandom(4). hex()'를 이용해서 랜덤 하게 세션 ID를 생성한다
random 4byte -> hex(16진수 변환)
이런 식으로 나오는 거 같다.
실험해 보자
예를 들어 os.urandom(1)로 생성된 바이트 데이터가 b'\xf0' 값이라면. hex()를 통해서 'f0'으로 변환된다는 것이다.
지금 보는 os.urandom(4)는 4byte -> 32bit -> hex() -> 8자리 문자열
하지만 8자리를 처음부터 무작위대입공격을 하기에는 너무 시간 소모가 크다.
그래서 코드를 다시 읽어봤다.
session_storage[os.urandom(1).hex()] = 'admin'
다시 보니 session_storage 가 있었다.
쿠키와 다르게 세션 스토리지는 클라이언트 측이 아닌 서버 측에 저장되어 있다
즉 admin의 session_id 가 서버에 미리 저장되어 있다는 뜻이다.
그렇다면 1byte -> 8bit -> hex() -> 2자리 문자열
(8 / 4 = 2)
경우의 수가 많이 줄어들었으니 무작위대입 공격이 가능하다.
python을 이용해 나온 값을 session_id에 대입하도록 하자.
session ID 값은 71이 나왔다.
'DreamHack > WEB' 카테고리의 다른 글
proxy-1 (0) | 2024.10.16 |
---|---|
web-misconf-1 (1) | 2024.10.10 |
blind-command (0) | 2024.10.10 |
web-ssrf (2) | 2024.09.26 |
pathtraversal (0) | 2024.09.11 |