[Dreamhack] simple_sqli_chatgpt 풀이
simple_sqli_chatgpt이다.
GPT센세와 함께 풀어보라고 한다..!
하지만 문제는 고작 레벨 1..
혼자 해결해보자
문제 페이지이다. Login이 있다. 나머지 About, Contact는 클릭해봐도 URL에만 #about, #contact 이 추가될 뿐 반응이 없다.
login 페이지이다.
input으로 userlevel을 받는다.
소스코드 ㄱㄱ
#!/usr/bin/python3
from flask import Flask, request, render_template, g
import sqlite3
import os
import binascii
app = Flask(__name__)
app.secret_key = os.urandom(32)
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
DATABASE = "database.db"
if os.path.exists(DATABASE) == False:
db = sqlite3.connect(DATABASE)
db.execute('create table users(userid char(100), userpassword char(100), userlevel integer);')
db.execute(f'insert into users(userid, userpassword, userlevel) values ("guest", "guest", 0), ("admin", "{binascii.hexlify(os.urandom(16)).decode("utf8")}", 0);')
db.commit()
db.close()
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
return db
def query_db(query, one=True):
cur = get_db().execute(query)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
@app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
@app.route('/')
def index():
return render_template('index.html')
@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}'")
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)
/login 하나 달랑 있는데 소스코드가 꽤나 길다..
login 함수를 보자
@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>'
login 함수이다. request method가 GET이면 login.html을 띄워주고,
아니면 userlevel 값을 받아 userlevel이라는 변수에 저장한다.
그리고 userlevel을 가지고 SQL 쿼리를 만들어 return 값을 res에 저장하고, res[0]을 userid, res[2]를 userlevel에 저장하고,
userid가 admin이고, userlevel이 0이면, FLAG를 출력해준다.
아주 간단한 문제다.
res = query_db(f"select * from users where userlevel='{userlevel}'") 에서 input인 userlevel을 전혀 필터링하고 있지 않으므로
input에 0' and userid=admin# 을 넣어주면 끝이다.
안된다.. 왜지 안될 리가 없는데
뭔 짓을 해도 안된다. 똑같이 테이블 만들어서 실험해봤는데도 여기서만 안된다.. 왤까..
하면서 500 ERROR에 대해 찾아보던 중
아
망치로 머리를 한 대 맞은 느낌이다.
MYSQL이 아닐 수도 있겠구나
#!/usr/bin/python3
from flask import Flask, request, render_template, g
import sqlite3
import os
import binascii
sqlite를 사용한다
sqlite는 #으로 주석 처리를 하지 않는다
??
소스코드를 잘 보자 자만하지 말자 소스코드를 잘 보자 자만하지 말자 소스코드를 잘 보자 자만하지 말자 소스코드를 잘 보자 자만하지 말자