2022年3月19日〜20日にかけて、所属しているCTFチームzer0ptsで、zer0pts CTF 2022という大会を開催したのでその記録と反省です*1。提供した問題については別のエントリにまた書こうと思います。
諸情報
開催期間 | 2022-03-19 09:00:00 +09:00 〜 2022-03-20 21:00:00 +09:00 (36h) |
登録チーム数 | 1034 |
1点以上獲得したチーム数 | 632 |
Welcome / Survey 以外の問題も通したチーム数 | 264 |
昨年のzer0pts CTF 2021と比べると登録チーム数や1点以上獲得したチーム数に関しては2/3程度になっていますが、Welcome/Survey 以外を通した(=非自明な問題を解いた)チームは昨年より多くなっており、実質的な参加者は増えていそうです。登録チーム数の違いは、スコアサーバがいつから立っているか、というところで変わっていそうですね。今年は「どうせみんなギリギリまで登録しないでしょ」と言って結構ギリギリまでサーバを建てるのをサボったので、その影響かなと思っています。
個人的には去年と同等程度の盛り上がりを維持しつつ、去年と同じかそれ以上の歯ごたえのある問題を提供できたこと、さしたるインシデントもなく開催できたことに胸をなでおろしています。
インフラ
未だにかなりプリミティブなことをやっていて、ひたすらDroplet(AWSでいうEC2のDigital Ocean番)をぽこぽこたてて、それを使っています。セットアップは共通のAnsibleでやって、Dockerをインストールしたり、Special IPへのアクセスを禁じるiptablesを仕掛けたり。このiptablesは特定の参加者をbanする仕組みでもあるのですが、未だに使ったことはありません。今年はDropletを建てる部分をterraformでやることにして、ドメインとの紐付けやらなんやらをそっちで管理することにしたらちょっとだけ楽でした。
問題サーバはいくつかDropletを建てて、基本的にはその上でdocker-compose up -d
をしてもらう、という運用を引き続きやっています。セットアップ用のAnsibleでファイルの配置や、tcpdumpの設定を事前に行っておき、起動だけは作問者におまかせする、という感じですね。dockerで環境を分けているので、負荷が許せばということでいくつかの問題は同じインスタンスに建てたりしています。1インスタンスに2〜3問が共存している感じ。基本的にはこれで全然問題なくて、インスタンスのスペックをフルに使えているかというとこれでもまだまだ、くらいですね。何かの拍子にどこかの問題で様子がおかしくなって、負荷が高まったりする(例えばプロセスが無限に増殖するとか)と他の問題が巻き添えになるので問題の負荷をどう読むか、共存をどの程度やるか、というのは難しいところです。このあたりもコンテナアプリケーションのホスト基盤みたいなものを用意すれば考えることが減るんですかね。いざというときに(インフラにそんなに詳しくない作問者でも)触って調査しに行けるような素朴さも維持していきたいので難しいところです。
スコアサーバも問題サーバと同様ただのDropletで動かしていて、落ちたら嫌だなと思って4vCPU 8GBメモリのそこそこリッチ(当社比)なインスタンスを建てましたが、メトリックの様子を見ているとこれの半分でもまだ余裕、1/4のサイズでピッタリくらいの負荷かな、という感じです。今回はけちってデータベースやRedisもマネージドサービスを使うのをやめて、一つのDropletの上で動かしていてましたが、登録チーム数が1000チーム数くらいのCTFならこれで十分ということがわかって良かったです*2。
kosenctfx
kosenctfxというのはここ1年半〜2年くらい、我々の開催するCTFで利用しているスコアサーバのことで、毎回フロントは書き変えたり書き直したり、バックエンドにも機能を追加したりしています*3。今年注力していたのは、スコアボードのstatic化の部分です。
CTFのスコアサーバはCTFの開催期間中はどんどんデータが更新されてfetchもmutateもたくさんする、バリバリのWebアプリケーションといった感じなのですが、一度CTFが終わった後は更新されるデータはなくすべてのデータがstaticになる、という性質を持っています。CTFの終了後もスコアサーバは公開し続けたいが、わざわざWebアプリケーションとしてホスティングすることはない、ということで毎年CTFの終了後にスコアサーバを書き換えてstatic化していたのですが*4、今年やっとNext.jsを使っている恩恵に預かって書き換えを最小化してstaticなスコアボードを生成できるようになりました。今ではグローバルに存在するisStaticMode
という変数をtrueにしてからyarn build && yarn export
をするだけでstaticなスコアサーバが生成できて非常に便利です*5。
TSG CTF 開催記 - 博多電光 をみるとTSGでは2019年時点でできていたということなのでかなり遅れをとっていますが、こんなに楽になるなら早くやっておけばよかったです。
追記
その後もう一つ修正が必要な点を見つけました。GitLab Pagesでホスティングしてみたところ https://2022.ctf.zer0pts.com/tasks
のようなページに直接アクセスすると、 tasks/
ディレクトリが優先されて tasks.html
は読んでくれないので 404 になってしまうんですね。これは next.config.js: exportPathMap | Next.js に従ってオプションを追加したあとでyarn export
をし直して解決しました
準備/作問
CTFの準備とは9割作問ですと毎日言ってますが、つまり作問の話です。今回のzer0pts CTFはかなり前、BSides Ahamedabad CTFの運営が終わってすぐですから昨年の11月にはやるぞという話が上がって準備を始めていましたが、結局過去一番の焦燥感でした。ptr-yudai, keymoonが精力的に活動していたpwnは十分な質と量が揃っていたのですが、他のカテゴリはcryptoが数問あるだけで、あとは焼け野原といった様相でした。
結局ptr-yudaiやkeymoonがwebやらmiscやらrevやらcryptoやらを作ってくれてギリギリ(本当にギリギリ)なんとかなったわけですが、今回はたまたまなんとかなったという感が否めません*6。zer0ptsはチームとしてはそこそこの人数を抱えていて、各分野に優秀な人材が揃っているはずなのですが、負荷がうまく分散されて十分早く問題が揃わないのは課題です。
しかしCTFの問題を作るのは非常に難しく一筋縄ではいかないものでコントロールはほとんど不可能という認識もあるし、CTFを開催するためにだれかがマネジメント業をするはめになるのも(それはきっと楽しくないので)避けたいとも思っています。難しいですね。結局解決策は自分がめっちゃ頑張ってcryptoを完璧に作って他のジャンルにも手を出すとかになってしまいそう。到底実現不可能なわけですが……
作問チェック不足
上記のような作問の遅れが何をもたらすかといえば、作問チェックの不足です。ギリギリにできた問題がチェックされないのもそうですが、十分余裕をもって作られたはずの問題も、チェックに回れる余裕のある人材の不足から、確認を経ず世にでてしまうということになってしまいました。なんとかならないか……
運営の様子
私、ptr-yudai、keymoonの3名がボイスチャットをつないで対応していたほか、作問者は質問の対応ができるように待機してくれていたようです。運営の様子と行っても問題が壊れていないか非想定解法で解かれていないかということを確認したり、まだ完成していない問題を急いで作ったり(!)、非想定解法で解かれてしまったのでリベンジ問題を準備したりといった様子でした。
開始から6時間と少しがたったあたりでやっと落ち着いて、boardgame arenaをしたり、discordに新しく追加されたsketch headsをやったりできるようになりました。しかし問題があって、3人だとイマイチ盛り上がりが足りないんですよね。その点、運営二日目にyoshikingが参加したときはもりあがりました。やっぱりhaxballやな……!
それにしてもCTF運営中に運営がボードゲームをしてるってあんまり想像できないですよね。しかしこれが楽しい。ちゃんとボードゲームを楽しめるように完璧に準備できるようになりたい。
まとめ
- 平穏無事にzer0pts CTF 2022を開催できてよかった
- 今年は問題の準備が特に遅れたのが課題です
参加してくださった皆様ありがとうございました。あとは皆様のwriteupとsurveyを見るのが楽しみです。よろしくおねがいします。
それでは次はCake CTF 2022(あれば)でお会いしましょう。zer0pts CTF 2023は、どうでしょうね。あると良いなと思っています
*1:余談だけど、CTFを開催した時のエントリのタイトルどうしてたっけなと思って自分のブログを遡ったら、「振り返り」と「開催記」が半々くらいでした
*2:このあたりは前回のBSides Ahmedabad CTFのときにコストかかるけどケチってもいいかな、ということを書いたらatpons先生に大丈夫でしょ、というお言葉を頂いて踏み切ることができました。ありがとう!
*3:例えば前回のCTFあたりからスコアの遷移のグラフがめっちゃ細かくなったりしてる
*4:https://2021.ctf.zer0pts.com や https://2021.cakectf.com のような感じ
*5:実際にはgetStaticPathsのfallbackがfalseじゃないとだめ、みたいなエラーを受けてそこは書き換えたりしました。SSR/SSGのこと何もわからず勘でやっている……
*6:ptr-yudaiがいるなら大丈夫という話もあります