$ cat writeup.md…
$ cat writeup.md…
hackthebox
Task: HTB-style OAuth2 SSO web app (nginx + Express/passport client + Go/Gin provider) with a teacher Puppeteer bot that submits the flag at startup. Solution: win a registration race for the fixed student account, then use a text/plain JSON CSRF (Gin ShouldBindJSON ignores Content-Type) delivered via the bot's /submit-url to swap the shared cookie jar's SSO token to our session, so the bot submits the flag into our own account.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Homework? Never heard of her. Let's dance.
A single-domain education platform protected by an OAuth2 SSO provider:
nginx (internal port 1337, mapped to a random external port per instance) routes by Host header.
edulearn.htb → Express client app (Node.js, EJS, passport-oauth2) on 127.0.0.1:3000.sso.edulearn.htb → Go/Gin OAuth2 SSO provider on 127.0.0.1:3002.302-redirects unknown hosts to edulearn.htb (preserving port).puppeteer-core, HeadlessChrome 130) runs inside the container, resolves both hosts to 127.0.0.1, and has no useful external egress.JWT_SECRET, CLIENT_SECRET, SESSION_SECRET, teacher/student passwords) are generated per-container with openssl rand — not guessable or forgeable.Goal: read the real flag, which the bot submits into a student assignment once at container startup.
bot/index.js initialSetup(), runs ONCE at startup)The bot drives a single Puppeteer browser whose pages all share one cookie jar. At startup it executes, in order:
loginUser(teacher, teacherPw) — SSO login form (sets SSO token cookie = teacher).loginSSO(teacher) — OAuth authorize, sets the client session = teacher.createAssignment ×3 — as teacher.registerUser([email protected], STUDENT_PASSWORD) — random password.loginUser(student, STUDENT_PASSWORD) — SSO login form.loginSSO(student, STUDENT_PASSWORD) — CRITICAL BUG: this function ignores its email/password parameters and authorizes using whatever token cookie is currently in the shared browser jar.submitFlagToAssignment() — types process.env.FLAG into the first assignment's submission textarea, submitting as the current client-session user.loginUser(teacher) + loginSSO(teacher) — restore teacher....
$ grep --similar