LoginSignup
6
1

CTFの作り方 [How to create CTF]

Last updated at Posted at 2023-12-18

CTFの作り方 ~How to create CTF~

Se4weed CTF 2023

はじめに

どうものりちゃんです。今年は阪神タイガースが優勝して素晴らしい一年でしたね。
もう今年も終盤ということで私にもアドベントカレンダーが回ってきました。
この記事を書いているときはちょうどセキュリティのイベントに参加していたので2023年を締めくくるべくCTFを作ることにしました。

0. 事前準備

事前にDockerとGitをインストールしておく必要があります。

1. スコアサーバの構築

今回は、高機能かつ簡単に構築できることから、スコアサーバーはCTFdを使うことにしました。

1.1 CTFdの構築

1.1.1 インストール・立ち上げ

CTFdをgit cloneして、試しに動かしてみましょう。

% git clone https://github.com/CTFd/CTFd.git scoreserver
% cd scoreserver
% docker-compose up --build

http://localhost:8000にアクセスしてみます。
Setup画面
すると、上のようになり、/setupにリダイレクトされ、セットアップ画面になりました。

1.1.2 スコアサーバーの設定

  1. 基本
    基本設定

  2. モード
    今回は、ユーザーモードを選択しました。

  3. 設定
    以下の通りに設定した。

  • Challenge Visibility: 問題を見る権限
    今回はPrivateを選択
  • Account Visibility: (他人の)アカウントを見る権限
    今回はPublicを選択
  • Score Visibility: (他人の)スコアを見る権限
    今回はPublicを選択
  • Registration Visibility: アカウント登録
    今回はPublicを選択
    設定
  • メールの確認: 登録時にメールを確認するか
    今回はDisableを選択
  • Teamsize: チームの最大人数
    今回は1とした
  1. 管理・スタイル・日程と時刻
    お好みで設定してください。
    image-3.png
  2. 統合
    今回はMLCと統合しないのでスキップします。

これでスコアサーバーの設定は完了です。

1.1.3 問題の投稿

試しにWelcome問題を作成してみましょう。

  1. localhost:8000/admin/challengesにアクセスします。
    Challengesの横にある"+"をクリックします

  2. ChallengeのTypeを設定します。今回はStandardを選択
    Standard: 1問の点数を固定する方式
    Dynamic: 正答者が多いほど点数が下がる方式

  3. 問題文や点数を入力
    今回は次のように入力
    問題
    Createボタンをクリック

  4. オプションやFlagを入力
    今回は次のように選択
    問題オプション
    Flag: Flagを入力します
    Case Sensitive(insenseitive): Flagの大文字小文字を区別する(しない)
    Files: ファイルを選択(今回はファイルはないので省略)
    State: 表示する状態か非表示の状態かを選択。今回はもちろんVisible。
    最後にFinishを押すと問題は作成されます。

  5. 問題を回答すると、以下のように正当できることが確認できます。
    Alt text

2. 問題の作成

2.1 どんなCTFにするか

どんなCTFにしたいか、コンセプトをある程度決めておきましょう。
具体的には、どんなスタイル(面白さ重視or難易度重視)で、どんなターゲット(CTF初めてor初級者or中級者or上級者)に向けての問題なのか、をある程度決めておくと良いでしょう。

2.2 どんな問題を作るか

どんな脆弱性を使ってどんな攻撃シナリオにするのかをある程度考えましょう。例えば、SQLインジェクションの中でもどこにSQLインジェクションの脆弱性があるかによってFlagを入手する難易度は変わります。
なので、「ログイン画面にSQLインジェクションを仕込んでパスワードをFlagにしよう」くらいで考えておきましょう。

どんな脆弱性を使うかは直近に話題になった脆弱性を使ってみたり、シンプルに好きな脆弱性を使ってみたりすると良いかもしれません。

私は、特定のフレームワークやライブラリを知らなければ解けない問題ではなく、一般的な脆弱性についての知識があれば解ける程度の問題で、ターゲットは初級者〜中級者というコンセプトで問題を作ることにしました。

2.3 問題の実装

注意:今回のCTFでは、Webのみとしました。
(Webくらいしかわからないため)

2.3.1 Web問

実装

先ほど考えたSQLインジェクションの問題を実装してみましょう。コンセプトは「ログイン画面にSQLインジェクションを仕込んでパスワードをFlagにしよう」でしたね。

注意: 問題サーバーとDockerのポートが競合しないようにDockerfileを書くようにしてください

では、実装してみましょう。今回は、WebアプリケーションをFastAPIとJinja2で、データベースをSQLiteを使用することにしました。

@app.post("/login")
async def login(request: Request, db: Session = Depends(session), username: str = Form(...), password: str = Form(...)):
    print(username, password)
    hashed_password = hashlib.sha256(password.encode()).hexdigest()
    query = text(f"SELECT * FROM users WHERE username='{username}' AND password='{hashed_password}'")
    result = db.execute(query).first()

    if result:
        return templates.TemplateResponse("success.html", context={"request": request, "message": "Login successful"})
    else:
        return templates.TemplateResponse("failed.html", status_code=401, context={"request": request, "detail": "Login failed"})

脆弱な部分はこのように実装しています。想定解としては、passwordパラメータにSQLクエリがInjectionできることを利用し、ブラインドSQLインジェクションを利用してadminのパスワードであるFlagを窃取されることを想定しています。('or '1'='1'--で解けると楽しくないよね!)

デバッグ
  • SQLインジェクションを起こすことができるか
  • パストラバーサルなど、想定外の解法を使うことができないか

を確認しました。想定外の解法を使って解くことができるのもCTFの醍醐味ですが、あまりに簡単にFlagが入手できてしまうような解法(パストラバーサル, etc.)を実行できないことを確認します。

今回は、PasswordのFormはSHA256でHash化されてDBに格納されているのでUsernameのFormからSQLインジェクションを起こせることを確認できました。
また、パストラバーサルは実行できないことを確認しました。(他に何か簡単にFlagが入手できる別解などあれば教えてください)

デプロイ

今回は無料で手軽にデプロイできるという観点からrender.comを採用しました。
render.comはGithubにプッシュすれば自動でデプロイしてくれるので非常に簡単です。

これで問題サーバーは完成です。

問題サーバーへの追加

下の図のようにして、1.1.3の要領で問題を投稿します。
Alt text

3. スコアサーバーのデプロイ

あまりにも時間がなかったため(言い訳)、render.comを利用しました。時間が空いたらAWSなりGCPなりにデプロイしたものを投稿するのでしばしお待ちを。。。

ということでよければ覗いていってください

Se4weed CTF 2023

4. 最後に

CTF遊ぶのも楽しいですがシナリオ考えながら作るのも楽しいです!
デプロイがだいぶ雑になってしまったのでデプロイだけまた記事書きます。(多分年明けになる。。。)では、良いお年を!!!

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1