Open roaris opened 1 month ago
app.py
#!/usr/bin/env python3
import flask
import sqlite3
app = flask.Flask(__name__)
def db_search(code):
with sqlite3.connect('database.db') as conn:
cur = conn.cursor()
cur.execute(f"SELECT name FROM country WHERE code=UPPER('{code}')")
found = cur.fetchone()
return None if found is None else found[0]
@app.route('/')
def index():
return flask.render_template("index.html")
@app.route('/api/search', methods=['POST'])
def api_search():
req = flask.request.get_json()
if 'code' not in req:
flask.abort(400, "Empty country code")
code = req['code']
if len(code) != 2 or "'" in code:
flask.abort(400, "Invalid country code")
name = db_search(code)
if name is None:
flask.abort(404, "No such country")
return {'name': name}
if __name__ == '__main__':
app.run(debug=True)
init_db.py
import sqlite3
import os
FLAG = os.getenv("FLAG", "FakeCTF{*** REDACTED ***}")
conn = sqlite3.connect("database.db")
conn.execute("""CREATE TABLE country (
code TEXT NOT NULL,
name TEXT NOT NULL
);""")
conn.execute("""CREATE TABLE flag (
flag TEXT NOT NULL
);""")
conn.execute(f"INSERT INTO flag VALUES (?)", (FLAG,))
# Country list from https://gist.github.com/vxnick/380904
countries = [
('AF', 'Afghanistan'),
('AX', 'Aland Islands'),
('AL', 'Albania'),
('DZ', 'Algeria'),
...
]
conn.executemany("INSERT INTO country VALUES (?, ?)", countries)
conn.commit()
conn.close()
flagテーブルのレコードを読み出すのが目標 countryテーブルからSELECTする時にプレースホルダーが使われていないので、SQLインジェクション出来るが、パラメータのバリデーションがあって厳しい
なにも思いつかないので解説を見る
文字列ではなく配列にするという発想らしい 全く思いつかなかった 配列を文字列の中に埋め込む場合、以下のようになる
a = [123, 'abc', '\'def']
print(f'test{a}') # test[123, 'abc', "'def"]
後はUNIONを使ったSQLインジェクションを行えば良い
https://alpacahack.com/challenges/country-db