誕生日に開催したCTFの環境構築と振り返り

# TL;DR
 - CTF開催にCTFdは非常に便利
 - GCE上でDockerコンテナを11個立てていたが, 問題なく動いた
 - 開催日程は事前に発表しておくと良い

# もくじ
 - [はじめに](#はじめに)
 - [CTFの環境構築](#ctfの環境構築)
   - [コンテストサーバ(CTFd)](#コンテストサーバctfd)
   - [Web問サーバ](#web問サーバ)
   - [Pwn問サーバ](#pwn問サーバ)
 - [CTFの運用](#ctfの運用)
 - [開催したCTFの振り返り](#開催したctfの振り返り)
 - [おわりに](#おわりに)

# はじめに
誕生日なのでCTFを開催するか, と言う気持ちで, 
2019年12月5日 0:00から2019年12月6日 0:00までの1日間にtaskCTFを開催しました。

taskCTFの開催にあたり行った環境構築や, CTF自体の振り返りを共有するために本記事を投稿します。

なお, taskCTFで使用した問題はGitHubで公開しています。
Dockerfile等のconfigファイル群, 問題およびwriteupが入れてあるので, もしよければご参照ください。
[task4233/taskctf19](https://github.com/task4233/taskctf19)

ご参加いただいた方々はありがとうございました！
おかげさまで思い出に残る誕生日になりました。

![score](https://i.imgur.com/CULFJ6Q.png)

# CTFの環境構築
GCEのインスタンス上でDockerコンテナを11個立てました。  

内訳は以下の通りです。

 - Web問サーバ2個
 - Pwn問サーバ5個
 - コンテストサーバ4個

![containers](https://i.imgur.com/nQffK3R.png)

GCEをしっかり使ったことが無かったため, 以下の記事を参考にして環境構築を行いました。特に困ったことはありませんでした。

[これから始めるGCP（GCE）　安全に無料枠を使い倒せ](https://qiita.com/Brutus/items/22dfd31a681b67837a74)


これらのコンテナは大きく分けて以下の3つのグループに分けられます。

## コンテストサーバ(CTFd)
以下の4つのコンテナはスコアサーバである, [CTFd](https://github.com/CTFd/CTFd)のために使用しました。

 - CTFd
 - DB
 - Redis
 - Postfix

CTFdは[documentation](https://docs.ctfd.io/en/latest/)があり非常に楽でした。
install方法は, flaskで手動立ち上げかdocker runかdocker-compose upが使用できたため, docker-compose upで楽をしました。

結果的に問題なく動いてくれたので良かったです。

先日参加したCTFのイベントでも運営の方にお聞きしたところ, 「CTFdを使い初めてからコンテストサーバが落ちたことがない」とのことだったので, CTFdは運用面で信頼性が高そうです(内部でredisが動いているので分散もうまいことやってくれます)

## Web問サーバ
以下の2つのコンテナはWeb問サーバに使用しました。

 - Bad Frontend-1
 - Bad-Frontend-2

php-fpmの公式イメージを使っていました。

以下, Dockerfileです。

```Dockerfile
FROM php:7.2-fpm
COPY php.ini /usr/local/etc/php

CMD ["php", "-S", "0.0.0.0:80"]
```

今回のWeb問はサーバにリクエストを送りつける問題だったので, 負荷が心配でしたが全く問題なかったようでした。
ちなみに, ローカルのPCからDOSもどきをしたのですが, GCEのCPU負荷を見ると殆ど影響がない様子でした。
アプリケーション自体の負荷が少なかっただけかもしれませんが, 結果的に何も起きなかったので良かったです。

## Pwn問サーバ
以下の5つのコンテナをPwn問サーバに使用しました。

 - peep
 - loop
 - leetspeak
 - 334
 - peep2

このうち, 上の3つは予想通りの実行が為されなかったため, 実際にポートを公開したのは下の2つのみでした。

今思うと, tcpで公開していたので, udpで公開した方がよかったのかもしれません。

Hostingにはmegumishさんに助言をいただき, xinetdを利用しました。

> https://twitter.com/megumish/status/1202466987332341760?s=20

1時間くらいで構築したので, 変な部分があるかもしれません。

以下, Dockerfileです。

```Dockerfile
FROM ubuntu:16.04
RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.ustc.edu.cn/g" /etc/apt/sources.list
RUN apt-get update && apt-get -y upgrade
RUN apt-get install -y lib32z1 xinetd
CMD ["/usr/sbin/xinetd", "-dontfork"]
```

このxinetdでホスティングしたものの, buffer overflowを狙った問題は正しくnetcatで繋がりませんでした。
format string attackを使う問題では問題なかったんですが......
原因がよくわからないので, xinetdについてわかる方がいれば助言をください。

# CTFの運用

以下がCPUの使用率です。

![cpu](https://i.imgur.com/bbJAEUN.png)

ホスティング時の3日とコンテスト終了間際にかなり高くなっています。

![network](https://i.imgur.com/FFHvHvG.png)

ネットワークのパケットトラフィックを見ると, 同じような時間帯に受信パケが多くなっています。そのため, Pwn問追加直後の影響だと考えられます。

**絶対に**サーバを落としてはならないと考えていたため, トラフィックが集中すると考えていた当初は, Pwn問を公開せずにコンテナ数を5つにしていました。

想定していたよりも負荷が少ない様子だったので, もっとコンテナを増やしても良かったのかもしれません。
何はともあれ, 結果的に安定したホスティングができ, 良かったと考えています。

# 開催したCTFの振り返り

開催後にアンケートを取り, 20人から回答が得られました。
全体の95%もの方が「楽しめた」と回答してくださり, 非常に嬉しかったです。

良かった点として頂いたご意見は, 大きく分けて以下の4点でした。

 - 理不尽なエスパー問題が無かった点
 - Pwn問があった点
 - 難しすぎず初心者でも楽しめた点
 - サーバが安定していた点

---

悪かった点として頂いたご意見は, 大きく分けて以下の6点でした。

 - 問題追加が遅かった点
 - 問題ジャンルが少なかった点
 - 同じ解法で解ける問題があった点
 - 開催するタイミングが事前公開されなかった点
 - 開催時間が分かりにくかった点
 - Miscが多すぎた点

> 問題追加が遅かった点
> 問題ジャンルが少なかった点

申し訳なかったです。しかし, できる全力を尽くしたので, 温かい目で見ていただきたいです。

> 同じ解法で解ける問題があった点

Pwn問とWeb問についてです。  
Pwn問では, FSAで解ける問題でFlagが同じ場所にあったため同じコードでFlagが取れてしまったようです。
常識なのかもしれませんが, **Flagの宣言場所は変えた方が良い**ようでした。  
Web問では, 同様にローカルプロキシを使っている方は同じ解法で溶けてしまったようです。もう少しひねった方が良かったかもしれないです。

> Miscが多すぎた点

Miscが多すぎたというか, **他ジャンルが少なかった**ということだと思います。

# おわりに
以上, 環境構築とコンテストの反省でした。
今回製作した問題は, 理不尽問題をなくすつもりで作っていたので, 感想で「理不尽問がなかった」という感想をいただけて非常に嬉しかったです。

感想等はTwitterのハッシュタグ[#taskctf](https://twitter.com/search?q=%23taskctf&src=typed_query&f=live)をご覧ください。

また, 環境構築や運用において不明点等があれば, 答えられる範囲で答えたいので, お気軽にお聞きください！

ここまでお読みいただきありがとうございました！
あなたも誕生日にCTFを開催してみてはいかがでしょうか？