ox0xo infosec tutorial

オンラインCTFを開催する

2018-12-15
CTF

このポストはインターネット上でCTFを開催する手順をまとめたものです。

インフラの準備

CTFの規模や出題傾向に応じてインフラのスペックを考慮します。 今回はさくらのVPSで4GB/SSDのインスタンスを1つ建てます。 ベースOSはUbuntu16.04です。

ssh

万が一にも第三者に操作されないようにSSH接続は公開鍵認証のみ許可しておきます。

sudo apt update && sudo apt upgrade

ssh-keygen -t rsa
mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# SSHクライアント側に必要な秘密鍵(id_rsa)を手元にダウンロードしておくこと
#$ ls -la .ssh
#total 20
#drwx------ 2 ubuntu ubuntu 4096 Dec 15 14:17 .
#drwxr-xr-x 4 ubuntu ubuntu 4096 Dec 15 14:17 ..
#-rw------- 1 ubuntu ubuntu  402 Dec 15 14:14 authorized_keys
#-rw------- 1 ubuntu ubuntu 1766 Dec 15 14:14 id_rsa

sudo sed -i -e 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
sudo systemctl restart sshd

もう一度VPSにSSH接続を試みてパスワードログインが弾かれたらOKです。 これ以降は手元にダウンロードした秘密鍵を使ってVPSにSSH接続します。 公開サーバ側の秘密鍵(id_rsa)は削除しておきましょう。

本当はクライアント側で秘密鍵/公開鍵を作成して公開サーバに公開鍵をアップロードする手順が適切です。

Docker

CTFdのデプロイにはDockerを使うのが簡単です。 docker-cedocker-composeのマニュアルに従って作業します。

sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce
sudo curl -L \
https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` \
-o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo systemctl start docker

CTFdのデプロイ

ctfdのマニュアルに従ってCTFdのDockerコンテナをビルドします。 ビルドが完了するまでには相応の時間がかかるので気長に待ちます。

sudo apt install vim git
git clone https://github.com/CTFd/CTFd.git
cd CTFd/
python -c "import os; f=open('.ctfd_secret_key', 'a+'); f.write(os.urandom(64)); f.close()"
vim docker-compose.yml
docker-compose up &
  • 記述例:docker-compose.ymlにSECRET_KEYを追記する
    version: '2'
    
    services:
      ctfd:
        build: .
        restart: always
        ports:
          - "8000:8000"
        environment:
          - SECRET_KEY=.ctfd_secret_key
    
  • 出力例:Dockerコンテナビルド完了
    ctfd_1   | Starting CTFd
    

ドメインの準備

今回は無料ドメインを取得できるFreenomを利用します。 空いているドメインを確保したらWebサーバのIPアドレスをAレコードに登録します。

Webサーバが名前解決できるようになったことを確認しておきます。

nslookup www.cctf2018.cf

HTTPSの有効化

CTFdのサービスをHTTPSで提供するためにリバースプロキシを立てます。 サーバ証明書はLet’s Encryptで取得します。

Let’s Encrypt

Let’s Encryptで証明書を取得するためには名前解決できるWebサーバが必要です。 ドメインは既に取得済みなのでファイアウォールとサーバアプリケーションを設定します。 今回は筆者の好みでnginxを使います。

sudo iptables -I INPUT 5 -p tcp -m tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT 5 -p tcp -m tcp --dport 443 -j ACCEPT

sudo systemctl stop apache2 && sudo systemctl disable apache2
sudo apt install -y nginx
sudo vim /etc/nginx/conf.d/default.conf
sudo systemctl start nginx
  • 記述例:default.conf
    server {
      listen 80;
      server_name www.cctf2018.cf;
    
      location / {
        root /usr/share/nginx/html;
      }
    }
    

Webサーバが準備出来たらLet’s Encryptで証明書を取得します。

sudo apt-get install letsencrypt
sudo letsencrypt certonly --webroot --webroot-path /usr/share/nginx/html -d www.cctf2018.cf
  • 出力例:秘密鍵(privkey1.pem)とサーバ証明書(cert1.pem)が生成された様子
    #
    #$sudo ls -la /etc/letsencrypt/archive/www.cctf2018.cf
    #total 24
    #drwxr-xr-x 2 root root 4096 Dec 15 15:42 .
    #drwx------ 3 root root 4096 Dec 15 15:42 ..
    #-rw-r--r-- 1 root root 1899 Dec 15 15:42 cert1.pem
    #-rw-r--r-- 1 root root 1647 Dec 15 15:42 chain1.pem
    #-rw-r--r-- 1 root root 3546 Dec 15 15:42 fullchain1.pem
    #-rw-r--r-- 1 root root 1704 Dec 15 15:42 privkey1.pem
    

nginx

HTTPSのサービスを提供できるようにnginxでリバースプロキシを構築します。 nginxが受け取ったリクエストはローカルポート8000で動作しているCTFdに転送します。

sudo vim /etc/nginx/conf.d/ssl.conf
  • 記述例:ssl.conf
    server {
      listen  443;
    
      ssl                   on;
      ssl_certificate       /etc/letsencrypt/archive/www.cctf2018.cf/cert1.pem;
      ssl_certificate_key   /etc/letsencrypt/archive/www.cctf2018.cf/privkey1.pem;
    
      ssl_session_timeout   5m;
    
      ssl_protocols              TLSv1.2;
      ssl_ciphers                HIGH:!aNULL:!MD5;
      ssl_prefer_server_ciphers  on;
    
      location / {
        proxy_set_header Host             $host;
        proxy_set_header X-Real-IP        $remote_addr;
        proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-User $remote_user;
        proxy_pass http://localhost:8000;
      }
    }
    

CTFd自身はHTTPで動作しているためリソースのリクエストにHTTPが利用されます。 これをHTTPSに書き換えるための設定も必要です。

sudo vim /etc/nginx/conf.d/default.conf
  • 記述例:default.conf

    server {
      listen 80;
      server_name www.cctf2018.cf;
      rewrite ^(.*) https://www.cctf2018.cf$1 permanent;
    }
    

設定が完了したらnginxを再起動します。 WebブラウザからCTFdにアクセスしてSetupが表示されればOKです。

sudo systemctl restart nginx


Content