st98 の日記帳 - コピー

なにか変なことが書かれていたり、よくわからない部分があったりすればコメントでご指摘ください。匿名でもコメント可能です🙏

DEF CON CTF Qualifier 2024 writeup

5/4 - 5/6という日程で開催された。undef1nedで参加して11位。私はGilroyでしか貢献できていないが…

リンク:


[Exploitation 100] Gilroy (39 solves)

(URL)

ソースコードはなし。

どのようなアプリか

与えられたURLにアクセスして、チームごとに割り当てられたチケットを入力する。これでundef1ned向けの環境が用意されるっぽい。チームごとの管理メニューは次の通りで、今回攻撃する対象であるフォーラムへのリンクや、このフォーラムのDBを初期化するリンクがある。

フォーラムは次のような雰囲気。なかなか凝っている。

ページの下部には Administered by: … という項目があり、jasper 8892396092 というユーザが管理者であることがわかる。このユーザとしてログインするか、もしくは新たに管理者であるユーザを作ればよいのだろうか。

適当なユーザで登録・ログインしてみる。group という項目がユーザの権限というか、ロールを意味しているのだろうけれども、これは normal となっている。なお、jasper 8892396092groupadmin だ。

フォーラムで新たなスレッドを立てたり、スレッドに対して返信したりもできる。なお、スレッドを立てる際にGIF画像を選んでタグとすることもできるが、BAN ME など特定のタグを指定するとBANされてしまう。BANされるとユーザの groupbanned となり、スレッドを建てられなくなってしまう。

group を好きな値にする

まず、管理者であるユーザを乗っ取る方法はないか考える。スレッドや返信でXSSができないかと考えたが、<s>test</s> のようなタイトル・内容で投稿しても、特殊な文字がエスケープされてしまう。特定のタグを使用するとBANされるけれども、このとき管理者が内容のチェックのために巡回してくるのでは、またその際の管理者の画面ではXSSが発生しているのではと考えたが、残念ながらそんなことはなかった。

SQLiが起こっていそうな雰囲気もない。管理者のパスワードのクラックも考えたが、さすがにもっとまともな解法であってほしいと考え、試すのは後回しにした。管理者であるユーザの乗っ取りは一旦諦めて、新たに管理者であるユーザを増やす方法はないか考える。

Mass Assignmentのように、本来フロントエンド側では存在していないパラメータを増やすことで、バックエンド側で受け付けてくれるのではないかと考えた。ユーザ登録時に <input name="group" type="hidden" hidden="" value="hoge">group というパラメータを増やしてみる。すると、作成されたユーザの group が空欄となった。本来 normal が入るべきところ、変な値に書き換えることができているらしい。

group というカラムに直接 normaladmin のような文字列が入っているのではなく、それらに対応する数値が入っているのではないかと考える。<input name="group" type="hidden" hidden="" value="0"> に変えると banned という、本来はBANされたユーザに付与される group になっていた。

<input name="group" type="hidden" hidden="" value="2"> では、次のように "An admin already exists" というエラーメッセージが表示された。2admin に対応するらしいが、すでに jasper 8892396092 という admin が存在しているために登録できないようだ。

管理者になる

ここからどうするか。まず jasper 8892396092 を管理者の座から引きずり下ろすことはできないかと考える。スレッドの投稿時に先程と同じ要領で投稿者のIDを書き換えることで、jasper 8892396092 になりすますことができ、またこのときにBANされるタグを使用することで、jasper 8892396092 をBANさせる(つまり、groupadmin から banned に変更させる)ことができるのではないかと考えた。しかしながら、poster, author, uid, userid, user_id, …と思いついたパラメータ名を試したものの、どれもダメだった。

わざわざフォーラムのDBを初期化できるようになっていることが気になる。DBの初期化後にしばらく管理者がいない時間がもしあれば、その間にrace conditionによって、先程の方法で jasper 8892396092 より先に管理者になれるのではないかと考えた。しかしながら、何度か試しても不発だった。

ユーザ登録時の group の値の検証と、その後のログイン等での検証とで、どの値を admin とするかという処理が異なるのではないかと考える。つまり、登録時には admin ではないとされるものの、それ以降の処理では admin とされるような値があるのではないかと考えた。<input name="group" type="hidden" hidden="" value="0002">0002 という値を group に突っ込んでみたところ、管理者になることができた。

Admin というリンクがトップページに増えている。これをクリックするとフラグが得られた。