https://dreamhack.io/wargame/challenges/1744
Logical
설명 간단한 논리를 깨다 Description break the simple logic
dreamhack.io
일단 파일을 다운받아보고, 웹 사이트에 접속해보자.
간단한 로그인 창이 보인다.
코드를 살펴보자.
code
from flask import Flask, render_template, redirect, request, make_response
from random import randint
from hashlib import md5
from sqlite3 import connect
app = Flask(__name__)
hidden_dir = '/dir_' + str(randint(1, 99999999999999999))
@app.route('/', methods=['GET','POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
if not login_check():
return render_template('login.html', error='Something wrong with the login details. Try again.')
else:
return redirect(hidden_dir)
else:
return make_response(405)
@app.route(hidden_dir)
def hidden_endpoint():
return render_template('hidden.html', FLAG=open('flag.txt').read())
def login_check():
uname = request.form.get('uname', '') # uname이라는 변수에서 값을 가져옴
password = request.form.get('password', '')
if not uname and not password:
return False
connection = connect("logical.db")
cursor = connection.cursor()
query = ("SELECT uname, password FROM users WHERE password = '{}'").format(md5(password.encode()).hexdigest())
usrname = cursor.execute(query).fetchall()
name = usrname[0][0] if usrname and usrname[0] and usrname[0][0] else ''
return name == uname
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=False)
hidden_endpoint() 함수에서 hidden.html 페이지를 렌더링할 때, 플래그를 출력한다. hidden_dir을 알 수 있다면 플래그를 알아낼 수 있으나 randint의 범위가 (1, 99999999999999999) 이므로 brute-force 공격은 힘들 것 같아보인다.
def login_check():
uname = request.form.get('uname', '') # uname이라는 변수에서 값을 가져옴
password = request.form.get('password', '')
if not uname and not password:
return False
connection = connect("logical.db")
cursor = connection.cursor()
query = ("SELECT uname, password FROM users WHERE password = '{}'").format(md5(password.encode()).hexdigest())
usrname = cursor.execute(query).fetchall()
name = usrname[0][0] if usrname and usrname[0] and usrname[0][0] else ''
return name == uname
입력받은 password를 기반으로 검증 후, 만약 db에 해당 해시화된 password가 존재하면 해당 db의 usrname을 가져와서 name 변수에 저장한다.
취약점은 오로지 password를 통해서만 검증하고, uname이 올바른지 여부는 신경쓰지 않는다는 것이다. 애초에 password를 해시화해서 저장하므로 sql injection 공격은 힘들 것으로 추정되지만, password만으로 검증하므로 password가 db에 존재할 경우 login_check를 우회해서 hidden 사이트로 접속할 수 있을 것이라고 추측해 볼 수 있다.
payload
기본적으로 db에는 빈 문자열이 저장되어 있다.
uname과 password를 빈 문자열로 보내되, 기본적으로 password는 md5 해시화해서 db에 저장하는 것 같으므로, password에서 빈 공백을 md5 해시 처리해서 보내보자.
아래와 같이 타겟 사이트에 curl 요청을 보내보자.
curl -X POST -d "uname=&password=d41d8cd98f00b204e9800998ecf8427e" http://host1.dreamhack.games:18919/
login_check 함수를 우회해서 hidden_dir의 주소가 나오는 것을 확인할 수 있다.
해당 디렉토리의 주소로 가 보면
http://host1.dreamhack.games:18919/dir_94778810868010993
플래그 발견
'보안 > Web hacking' 카테고리의 다른 글
[Dreamhack] baby-jwt (0) | 2025.01.31 |
---|---|
[Dreamhack] 삐리릭... 삐리리릭... (0) | 2025.01.30 |
[Dreamhack] Fly me to the moon (0) | 2025.01.20 |
[Dreamhack] Relative Path Overwrite Advanced (0) | 2025.01.19 |
[Dreamhack] access-log (0) | 2025.01.11 |