SECCON Beginners CTF 2024 writeup

久しぶりの投稿です。最近CTFから離れ気味でしたが、子育てが落ち着いてきたので、CTFに参加しはじめました。
なお、初日は子供が公園で遊んでいる中CTFしてました(他の親御さん、大変助かりました)
今回は6問(welcomeを含めると7問)を正解し、524ptで168位でした。

[misc]getRank

数字を予想して、一致していたらスコアが加算されていくゲーム。
で、現在のスコアに応じてランキングが決まっていて、ランキングの1位になれば見事フラグをゲットできるシステム。

フラグをゲットするのには以下の条件が必要
・スコアが10の255乗より大きいこと(ただし、スコアが10の255乗より大きい場合はスコアを10の100乗を割った数がスコアとなる)
・スコアは300文字以内

スコアを加算する部分はサーバと通信していないので、こちらは改ざんし放題。問題は10の255乗より大きい値にしなければいけないが、10の255乗より大きい場合、スコアが10の100乗で割った値となってしまうので、フラグをとるには10の355乗以上の数が必要になり、正攻法ではいけないことがわかった。

サーバ側のソースを見るとリクエストとして渡されたスコアの文字列をparseIntで数値に変換して処理を行っているので、そこに何かあるのではないかとparseIntの仕様を調べてみることに。

すると、parseIntの第二引数(基数)を指定していない場合、入力値を0xから始めると16進数で解釈してくれるということがわかった。

そのため、スコアの文字列を0xFFFFF…と300文字ぴったりになるようにして、リクエストを送信したところ、フラグをゲットした。

[misc]clamre

こちらはflag.ldbの内容が以下のようになっており、0/^から始まる部分がシグネチャのパターンになっているように見える。
※\x63\x74\x66がctfになっている。

ClamoraFlag;Engine:81-255,Target:0;1;63746634;0/^((\x63\x74\x66)(4)(\x62)({B)(\x72)(\x33)\3(\x6b1)(\x6e\x67)(\x5f)\3(\x6c)\11\10(\x54\x68)\7\10(\x480)(\x75)(5)\7\10(\x52)\14\11\7(5)})$/

最初はよくわからなかったのですが、途中からある\の後に数字がある場合は正規表現のカッコに対応していることがわかり、それをもとに解読した結果、フラグをゲットすることに成功した。

[web]wooorker

ページにアクセスしても「No token provided. You need to login .」と表示されるだけ。loginが必要なのだが、管理者権限でログインしないとフラグを獲得できない。

脆弱性報告botのほうは報告するURLにアクセスすると管理者権限でログインするというクローラになっている。また、ログイン画面のソースでは、ログインに成功するとnextというクエリパラメータに設定されたURLに遷移しており、その際にtokenがクエリパラメータに付与されるような動きとなっていた。

なので、Webhook.siteというサイトを使って、そのリクエストを受け取ろうとしたところ、なぜかうまく受け取れず、結局このブログサイトのURLを設定して、アクセスログからtokenのクエリパラメータを取得しました。

[15/Jun/2024:23:04:15 +0900] "GET /?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNzE4NDYwMjUzLCJleHAiOjE3MTg0NjM4NTN9.xRMU0Xt1Bmfp6r7-9Mr-4-BgjqAZqDE8kvqoZ2v0VZc HTTP/2.0" 200 11179 "http://wooorker:34466/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/125.0.6422.26 Safari/537.36"

そのtokenをそのままクエリパラメータに設定して自分のブラウザからアクセスすることでフラグゲット。

[web]ssrforlfi

サイトを見ると、?url=xxxxで指定したURLにアクセスして、そのページの内容を表示するらしい。

肝心のフラグは環境変数に設定されており、その内容をどうやって取得するかというもの。

urlに使用できるスキーマはhttpかhttpsかfileしか選べず、httpやhttpsの場合、localhostが禁止されていて、fileスキーマの場合だと、file://以降のパスが実在するファイルだとエラーであり、かつ..の使用も禁止されている。

fileスキーマの仕様を調べてみたところ、file://の後にlocalhost/とつけることができるらしい(file:///はlocalhostを省略したものらしい)ので、https://ssrforlfi.beginners.seccon.games/?url=file://localhost/proc/self/environ にアクセスし、環境変数の内容からフラグをゲットした。

[web]wooorker2

こちらは先ほどのwooorkerを進化させたもの。
修正差分を見るとログインに成功するとnextというクエリパラメータにトークンを設定してURL遷移していた部分が、フラグメント識別子になっていた。
flag.html(とflag.js)はそのフラグメント識別子からトークンを取得して/flagにアクセスしていたので、そのソースを自分のサーバにおいて、/flagを取得する際にクエリパラメータにトークンを付与してアクセスするようにして、自分のサーバのアクセスログからトークンを取得した。

[16/Jun/2024:09:59:03 +0900] "GET /flag?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNzE4NDk5NTQ0LCJleHAiOjE3MTg1MDMxNDR9.EhRYzoN71n7uZwrV0uV2Pr_jST6Nxqg0kcOKjKVj8rQ HTTP/2.0" 404 1299 "https://rakuha.com/hoge/flag.html" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/125.0.6422.26 Safari/537.36"

そのトークンを同じようにフラグメント識別子として設定したうえで自分のブラウザからアクセスすることでフラグゲット。

[pwnable]simpleoverflow

コードは以下のとおり。

int main() {
  char buf[10] = {0};
  int is_admin = 0;
  printf("name:");
  read(0, buf, 0x10);
  printf("Hello, %s\n", buf);
  if (!is_admin) {
    puts("You are not admin. bye");
  } else {
    system("/bin/cat ./flag.txt");
  }
  return 0;
}

変数bufにreadで入力した文字を入れているが、bufは10byteしか確保されておらず、readは0x10なので16byte読み込むことから、10文字以上適当に入れれば、is_adminの変数の内容が上書きされ、フラグの内容が読み込める。

解きたかった問題

・[crypto]Safe Prime
 今までCTFでcryptoには手を出せずにいたが、ようやく解き方がわかってきた。
 2p^2 + p = nという方程式を解けばいいというところまでわかったが、ここからうまく計算できずタイムアップ。次回はなんとかとりたい。。。

・[reversing]assemble
 よくわからなかったが、ChatGPT君に助けてもらいながら最終問題までいったけど、そこでうまくいかず挫折。
 昔と違ってわからないことがあってもChatGPT君に聞けばある程度いいところまではいける世界線が見えたので、昔と違って変わったなーと思った

さいごに

今回は久しぶりに集中してCTFに取り組むことができました。
CTFを通じて新しい仕様を知ったり、新しい技術を知ったりと楽しみながら勉強できるので非常によい経験となりました。
また今後も(少し簡単な)CTFに参加していきたいです。

IPAの資格持ち(FE,AP,SC,DB,NW)。一応、情報処理安全確保支援士です。セキュリティ関連に興味あり。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です