SECCON 2015 決勝大会 intercollege に参加してきました!
こんばんは、いるかさんです!
時は遡り、1月の話になるのですが、SECCON 2015 決勝大会 に参加してきました!
個人的に、チーム参加なイベントにはいつも「Aquarium」として参加しており、今回も例に漏れず「Aquarium」として参加してきました。結果は、18チーム中10位でした。
今回、Attack & Defense形式ということで、生まれて初めて体験する競技でした。
事前に行った作戦会議から、本戦中のできごとなども踏まえ、記事を書きたいと思います。
今後 Attack & Defense に参加するチームの手助けになれば幸いです!
事前の作戦会議
事前の作戦会議は、決勝当日の夜行列車の中で行われました。
何分、初めての Attack & Defense なので、次のことに焦点をあてて作戦を立てました。
- そもそもどんな競技なのかを知る
- 最初に絶対やったことがいいことを決める
- 競技時間が短いので方針を決めてそれに沿った作戦を立てる
そもそもどんな競技なのかを知る
CTFにはたくさん参加したことがありましたが、今回、チームメンバーに Attack & Defense を体験した人はいませんでした。
たまたま学内に、CTF for ビギナーズ2015 奈良(Attack & Defense) に参加した後輩がいたので、話を聞くことができました!
○ 防御点と攻撃点 サービスがいくつか稼働していて、それを正常に稼働させておくことで防御点を獲得する。 他のチームのサービスから情報を盗むと、攻撃点を得られる。 ○ ネット環境 競技用サーバはインターネットに繋げない。 パッケージのアップデートやスクリプトのダウンロードは直接できない。 ○ フラッグ情報以外は全員同じサーバ! アカウントのパスワードも同じ。なので、ログイン後にすぐにパスワードを変えないと、 勝手にログインされて攻撃される。 逆を言えば、そのことを知らないチームは格好の餌になるので、そこで得点を稼ぐチャンスは あるかもしれない。SSHでログインだけしておいて、潜んでおくとか。whoでばれるかも。 whoコマンド殺しておくのがいいか。
しかし・・・!!今回はルールが結構違っていました。主には、次のような点です。 (Slackでまとめてる内容をそのまま載せてます。)
○ SSH そもそもパスワードが最初から違うので、他チームのSSHへのログインはできない。 ○ 減点方式と奪点方式 奈良では、防御点を守るために、誰かの攻撃が成功するとみんな自分のサーバのサービスを落として 得点の保守に務めた。(攻撃されると、DBの1レコードあたり100点とられる。) 一気にマイナス10000点とかもありえた。 今回は、固定点ではなく、奪われたチームの得点を奪ったチームが3%獲得するというルール。 なので、マイナスにはならないが、奪われたチームの総得点が低いと、あまり点数をとれない。 よって、フラッグをSubmitするタイミングによっては、0点ということもありうる。 ただし、フラッグには有効期限があり、溜めておくことはできない。 そして逆に、自チームのフラッグが奪われた場合、自チームの点数が低ければ、被害が少ない。 ○ フラッグ追加方式 奈良と違って、フラッグが随時追加される! そのため、奈良の時は、自チームのフラッグを根こそぎ取られた場合、後は稼働させておけば 防御点を延々と稼げていたが、今回は追加されたフラッグを攻撃されうる。 また、奈良の時は、一度どこかのチームがSubmitしたフラッグは、それ以外のチームがSubmitしても 得点にならなかったが、今回は先取りした人が総取りということはない。 ○ サービスを落とした時にペナルティポイント 奈良の時は、サービスを落とすのは自由だったが、今回はサービスを落とすと、 防御点をもらえないだけでなく、その時点での総得点の3%を減点される。 つまり、得点する前にサービスを落としていても、ペナルティはない。
ルールの違いなどから、奈良の時にうまくいっただろう戦略のいくつかは、通じなさそうでした。
最初に絶対やることを決める
以上を踏まえ、開始直後は、次のことをやろうと決めました。
・ 開始直後 ○ ログイン後にすぐにパスワードを変える(事前にパスワードは4人で決めておきましょ) ○ DBのバックアップを自分のPCにとる ○ サービスのスクリプトのバックアップを自分のPCにとっておく ○ ファイル監視(不正なファイルのアップロードに備える?) ○ 各種ログのtailfを画面に表示する?
この中で、実際に実施できたのは、パスワードの変更とバックアップだけでした。
しかし、mysql
のroot
のパスワード変更が抜け落ちていたため、後々痛い目をみました(;´∀`)
DBのバックアップは、/var/lib/mysql
のバックアップをとらず、データベースのデータだけ
バックアップをとっていたので、復旧に時間がかかってしまったりもしました。
ファイル監視やログ監視が実現しなかったのは、ファイル監視を仕込む時間がなかったこと、
ログ監視をするための画面が足りなかったことが原因でした。もしモニタを持ち込めるなら、
ログ表示専用に1つ持ち込んでおいてもいいかもしれません。
方針を決めてそれに沿った作戦を立てる
大体競技内容が分かってきたので、方針を決めて作戦を立てようとしました。
方針的には、「ブラフ」とか「ダミー」色が強かったです。
次のような内容が挙がったりしました。
- [ダミー] 適当なポートで待ち受けるプログラムを用意してQRを表示する
ただし運営が事前にサービスを明示する可能性があり微妙 - [ダミー] SSHのポートを変更して22番はダミーのハニーポット的なものを走らせる
- iptables でアクセス元とアクセス先の監視
- DBMSを変更する (MySQLで動いてたらSQLiteにしてしまう、など)
しかし、結局どれも実現しませんでした。理由は簡単で、時間がなかったからです。
想像以上にやらないといけないことが明確で、かつ、それ故に攻撃が始まるまでの時間が短く、
その対応に追われることになり、非常に余裕がない感じでした。
そして体力の限界がきて、寝ました(つ∀-)
寝てたら夢で名案を思いついた!
寝台特急効果か、寝てたら名案を思いつきました。
結論から書くと、この案は実践できなかったんですが、かなり有力な案でした。
その案は、 リバースプロキシ型のWAF です。
この、PythonによるReverseProxyによって、ブラックリストを登録します。
そうすることで、攻撃パケットだけ防ぎます。
どのポートでも動かせ、かつ、SSL対応のスクリプト*1も転がってたので、だいたい対応できそうな感じでした。
万が一、攻撃を受けても、すぐブラックワードに登録すれば、かなり有効な対策になったんじゃないかと思います。
何故実践できなかったのか?
なんとかこのスクリプトを、朝起きてから競技開始前までに作成し、動作確認もできていました。
それにもかかわらず、なぜ実践できなかったのか?それは、落ち着いた対応ができていなかったからでした。
もともと、何のサービスが動かされるのか提示される想定でいたのですが、
サーバだけポンと渡され、何のサービスが動いているのか、また、何のサービスが動いていないといけないのかなどは、自分で調べる必要がありました。
今回は、3つのサービスが動いているという情報だけ提示されていました。
そのため、何が動いているのか調べて、見つけたサービスについてはすぐに脆弱性を探し、攻撃班と防御班が攻撃と防御を試みて、
その間にまた別のサービスを探すという、今考えれば、行き当たりばったりな感じになっていました。
ここできちんと、見つけたサービスからきちんとWAFを挟んでいけば、下手したら脆弱性を直さずに防御できてたかもしれません。
おそらく、現実的なインシデントが発生した時にも同じようなことになりかねないので、いろいろと考えさせられました。
本番開始
受付の様子。でかいRedBullの横にはAMATERAS零が映っています。
開始直後
開始直後は、5分か15分か忘れましたが、最初に準備タイムが与えられます。
この準備タイムの間は、攻撃はできますが、防御点は加算されません。
つまり、サービスを確認したり、落としたり、脆弱性を確認したり、という時間に使えます。
自チームは、iptablesでスコアサーバ以外からのアクセスを弾くようにしようとしたんですが、
結果的にNATが挟まれてて、そういうことはできませんでした。
問題となるサービス
今回は3つのサービスが動いており、それぞれに防御点と攻撃点がありました。
1つ目: 簡易ブログサービス
Webで簡易的なブログサービスが動いていました。
管理ページのパスワードが脆弱なので、そこを利用して管理ページヘログインすると
フラッグが書かれた記事が全部見えます。フラッグをスコアサーバへ送信すると得点となりますが、
随時フラッグがスコアサーバにより追加されてました。なので、攻撃は自動化しておくと楽でした。
更に、他チームがフラッグを投稿しても得点となるので、それを防ぐために
こちらが入手したフラグの記事はその場で削除するようにしておきました。
管理ページのパスワードを変更してしまうと、この脆弱性は使えませんので、
最後の方になると、どこのチームもこの攻撃はできなくなっていました。
2つ目: 競馬サービス
中身見てないので分かりませんが、node.js
で動いてるサービスで、
jsファイルを見ると、SQLインジェクションし放題なコードになっていました。
バインドを使えば簡単に防げるような雰囲気でしたが、
コードしか見てないので、実際のところどうだったのかは分かりません(;´∀`)
3つ目: サンドボックスサービス(Ruby, PHP, Python)
アップロードしたコードを実行できるというサンドボックスサービスでした。
言語はRuby, PHP, Pythonに対応していて、スコアサーバからフラッグを
出力するようなコードが投げられてました。このサンドボックスが脆弱で、
何でもやり放題な状態だったので、先にこのサービスを見つけて
脆弱性を利用していたチームは、かなりガッツリ攻撃ポイントを取れてたと思います。
このサービスに気付けたのがかなり後の方だったので、散々防御点を取られた挙句、
データベース壊されるという悲惨な状態だったり、そもそもアップロードしたコードの実行方法が
分からなくて(人権ないですね(´・ω・`))、ずっと詰まってたのが痛手でした。
アップロードされてる攻撃コードをそのまま流用し、他チームへの攻撃に使いましたが、
それが競技終了の20分前ぐらいだったので、(ノ∀`)アチャーって感じでした。無念w
反省点
- mysql の root のパスワード変更が抜け落ちていたのは論外か
- 攻撃の自動化だけでなく、フラッグsubmitも自動化しておかないと他のことができなかった。
何故ならフラッグには有効期限があり、早めにsubmitしないと得点にならないからである。 - 落ち着いてWAFを導入しておけばかなり違った結果になったと思われる。
- 新型MacBookを持って行っていたが、LAN繋いでる間は充電できなかったので、終了30分前ぐらいから残バッテリー量との戦いになっていて非常に良くなかった。
- 先に稼働しているサービスを全て把握しておくべきだった。
そうすればサンドボックスからいろいろ攻撃できていたと思われる。
終わりに
これほど楽しく面白いと思ったCTFは初めてでした!SECCON運営の中の方々と参加者の方々、貴重な機会をありがとうございました。
チームメンバーもブログ記事を書いているので、リンクを貼っておきます。
- naosuke2dx: SECCON2015 intercollege決勝大会参加
- iguto: SECCON 2015 intercollege 決勝大会
- mi: SECCON 2015 決勝大会 (intercollege)に参加してきました