A little something to get you started
ソースのheadをみると、背景画像としてbackground.pngを読んでいるっぽいので、URLにベタ書きして飛んでみるとフラグ発見。
レスポンスのContent-Typeがimage/pngではなくtext/htmlなのでそもそも画像じゃなさそう。
Micro-CMS v1
自分で、サイトのページを作成できるサイトで、タイトルと内容を入力できるようです。
flag0
ページを新規生成するとページのインデックスが8から始まります。既存ページとの間を調べていくとpage/5だけ403が帰ってきます。色々考えた結果、どうやらpage/edit/5で編集ページには飛べるっぽいです。(手探りで見つけた)そこの内容編集ページにフラグが残ってました。
flag1
編集ページのURLの末尾に'を入れてアクセスすると、フラグが得られます。http://ドメイン/page/edit/1'
想定としては、ルーティング処理の際に、ページのインデックスを'を含めそのまま処理を行ってしまい、エラーが起こる事があるよ。といった感じでしょうか?エスケープ忘れとかですかね。
flag2
ページ編集より、タイトルの部分に<script>alert('xss')</script>と入力し保存、トップページに戻ると仕込んだアラートとフラグを出力する謎のアラートが実行されました。多分、エスケープできていないって事を見つけたのがゴールという設定でしょうか?
flag3
内容記述部分は、scriptという文字をscrubbedにエスケープ?して値を保存するので、jsは仕込めなさそうです。が、HTMLタグは埋め込めるようです。サンプルページではbuttonタグが生きているので、<button onclick=alert("xss")>call</button>を仕込んで保存。見事alertが表示され、ソース部分にflag属性が追加されていました。
Micro-CMS v2
前の問題に認証機構が実装されたみたい。
flag0
既存ページをエディットしようとするとログインが求められますので、SQLインジェクションを狙ってみる。とりあえず' OR '1'='1' --とか入れてみる。するとエラーが表示された
Traceback (most recent call last):
File "./main.py", line 145, in do_login
if cur.execute('SELECT password FROM admins WHERE username=\'%s\'' % request.form['username'].replace('%', '%%')) == 0:
File "/usr/local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 255, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python2.7/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
raise errorvalue
ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1")
処理がわかりました。のちに気づきますが、request.form['username'].replace('%', '%%')はおそらく意味なしてない。処理の時点でデコードされているはず?なので、'とか普通に使えてそうです。エラー内でもちゃんと認識されているし。
処理をよくみると、adminsテーブルからpasswordカラムをとってる事がわかるので、次の処理はおそらくそれがフォームから入力されたパスワードと一致するかという事。
username: ' UNION SELECT '1' AS password# password: 1
ログインに成功するので、ホームに戻ると非表示だったページが出現するのでそこにフラグがありました。
flag1
全くわからなかったです。ログインしていない状態で、ページ編集のURLにPOSTで繋ごうとすると、フラグのページにリダイレクトします。POSTへの書き換えはZAPとかでブレークして書き換えました。
GET http://35.227.24.107/e05c78ea4d/page/edit/1 HTTP/1.1 # POSTに書き換え
試しに、flag0を用いてログイン済みで同じ事をすると400が返されました。なので、この問題の趣旨はおそらく、ログイン要求ページのリダイレクト処理に、不備がある事があるよ(GETだけを想定していて、POSTは想定外の動作をする)って事なのでしょう。勉強になります。。
flag2
username: ' OR '1'='1'#
で、エラーがunknown userからInvalid passwordに変わるのが確認できていたので、パスワードのブルートフォースで解くのかなと思ったのですが、Burpのフリーの速度が遅かったりhydraのパスワードリスト作るのピンときていなかったりで、諦めたらどうやらもう少し絞れるらしい。
username: ' OR LENGTH(password) = 5 #
で、パスワードの長さが一致するものを取得できます。上の数字部分は適宜変えて試しますが、結果的に長さは5。この手法はおそらくたくさん登録されている場合、あまり意味をなさないかもです。次の手法もそうですが。
' or password LIKE "%x"#
xには検索したい文字を代入します。LIKE句により、%は任意の文字数をさすようになります。replaceの影響で%%xに変化しますが、動作的には変わらなそう?詳しい人いたら教えてください。
%%x => 末尾の文字判定
x%% => 先頭の文字判定
%x% => 使用されている可能性のある文字。今回は長さが5と分かっているので追加で最大3文字見つかるはずです。
余談ですが、LIKE句の_は任意の1文字なので、これを使ってパスワードの長さを測るのもありです。
判定するときの目印ですが、帰ってくるエラーがPasswordのエラーの場合はクエリが成功しているので、予測は正しいと判断します。
BurpのIntruderを使って総当たりします。(フリー版はめちゃ遅いのでなるべく手数を減らす)まず末尾の1文字を当てに生きます。
proxyよりログインのリクエストを拾って、Intruderに登録します。
このリクエストではusernameの部分に以下のクエリを仕込んでます。
' or password LIKE "%x"#
そしてIntruderの画面で変化させる部分をマーク(add)

Payloadタブで、ブルートフォースを選んで使用する文字とパターンの長さを指定します。
元のページのstart attackボタンで開始すると下の結果が得られました。1つだけサイズが違うので目星はつけやすいはずです。
同じように先頭と中間文字も調べ次のような文字と推測ができました。
k + "eor"+ y
後は中間の並びを総当たりして終わりです。この時は、usernameには' OR '1'='1'を仕込んで、passwordクエリに総当たりを仕掛けました。

結果の画面撮ってないですが、ログインに成功し、フラグが表示されます。余談ですが、このパスワードはサーバ立ち上げ毎に変わるっぽいです。