Bypassing Access Control through OPTIONS Request + Method Smuggling: A HackerOne Finding
You know that feeling when you’re just poking around, kinda half-bored, and stumble onto something juicy? Yeah, that’s pretty much what happened here.
I was hacking on a private HackerOne program and noticed their frontend was super strict. Every time I tried hitting sensitive endpoints directly with a POST
or whatever, it would slam me with a 403. Gatekeeping hard.
But here’s the kicker: they were chill with OPTIONS requests. Like, totally letting them through. No questions asked.
So I’m thinking, “Yo, if OPTIONS is sliding past, what if I sneak something spicy inside it?”
Turns out, their backend respected the X-Http-Method-Override
header. Basically, you could tell it, "Hey backend, this isn’t really an OPTIONS... it’s a POST!" And guess what? The backend’s like, "Bet."
Here’s how it went down:
First try (Blocked AF):
POST /user/profile/exists HTTP/2
Host: api.[redacted].com
Authorization: Bearer <jwt>
Content-Type: application/json;charset=UTF-8
{"":""}
Response:
HTTP/2 403 Forbidden
No surprises. Frontend doing its job.
Second try (Sneaky Mode):
OPTIONS /user/profile/exists HTTP/2
Host: api.[redacted].com
X-Http-Method-Override: POST
Authorization: Bearer <jwt>
Content-Type: application/json;charset=UTF-8
{"":""}
Response:
HTTP/2 400 Bad Request
{"error":{"source":"user-svc","code":"BAD_REQUEST","message":"[username: must not be null]"}}
Boom. Backend actually processed it like a POST. Not perfect (because of missing fields), but the important thing? I bypassed frontend rules.
So… what was broken?
Frontend was all “no POSTs allowed” but forgot to be suspicious about OPTIONS. Meanwhile, backend’s like “yo fam, if you ask nicely with an override header, I’ll do anything you want.” Basically, they weren’t on the same page.
This “mismatch” was the sweet spot.
Impact
- Access Control Bypass Bad guys could sneak into endpoints that were supposed to be off-limits.
- Generic Exploit Not just one endpoint. Anywhere the frontend was blocking methods = game on.
Final thoughts
Honestly, it’s wild how a little “Options + Header Magic” can punch holes through beefy frontend walls. Always pays to try funky stuff when you’re bug hunting.
Stay sneaky.