← All casesConfidential · Anonymized
Case
#024
FinTech · Severity: High
API Logic Vulnerability
A multi-step API workflow exposed by the client permitted a state transition that bypassed authentication checks when a specific request-ordering condition was reproduced. The condition was not visible from standard testing paths and required a controlled race window. Once triggered, an unauthenticated caller obtained a session bound to an arbitrary user id.
Industry
FinTech
Scope
API · Infrastructure · Validation
Timeline
R·Q2 → V·Q2 → R·Q3
Closed
Q3
01
Impact
Authenticated identity takeover
Unauthenticated → arbitrary user_id, single request
Backend resource exhaustion
~4× normal DB pool utilization during reproduction
Application instability
p95 latency degraded on 3 of 6 downstream services
Blast radius
Full API surface authorization boundary
Impact vectors
- ›Application instability
- ›Authentication bypass
- ›Backend resource exhaustion
02
Reproduction
Steps below reproduce the finding against a staging replica. Where the reproduction affected a shared component, coordination was arranged before execution.
- 01Initiate the multi-step onboarding flow up to the state-transition endpoint.
- 02Prepare two concurrent requests: (a) a legitimate state-advance, (b) a crafted state-mutation with a substituted user_id.
- 03Dispatch (a) then (b) within a ≤ 40 ms window against the same backend replica.
- 04Observe: session established under the substituted user_id; downstream authorization treats caller as authenticated.
- 05Repeat across replicas to confirm the race is not replica-local.
03
Vulnerability
# state-advance handler — trusted transition, no idempotency key
def advance_state(request):
session = load_session(request)
incoming = request.json
# trust boundary: caller can supply user_id on transitions
session.user_id = incoming.get("user_id", session.user_id)
session.stage = next_stage(session.stage)
save_session(session)
return ok(session)04
Mitigation
Client-side mitigation shipped and validated during the engagement. Reference patch below.
# state-advance handler — bound, idempotent, authorized
def advance_state(request):
session = load_session(request)
expected_user = session.user_id
if request.json.get("user_id", expected_user) != expected_user:
return forbidden("user_id may not change on transition")
with idempotency_key(request):
session.stage = next_stage(session.stage)
save_session(session)
return ok(session)05
Retest & Verify
- ✓Reproduction path exercised against staging replicas after fix deployment — 0/2000 attempts succeeded.
- ✓Production replicas exercised under a controlled window — 0/500 attempts succeeded.
- ✓Idempotency-key path verified: duplicate concurrent submissions collapse to a single state advance.
- ✓Downstream service latency returned to baseline within one deployment cycle.
06
Deliverables
- ▊Technical Report (Markdown + PDF)
- ▊Reproduction artifacts (request bundle, sequence diagram)
- ▊Mitigation guidance with reference patch
- ▊Retesting report (post-fix)
- ▊Final validation memo
07
Sign-off
Handled by
Epulyx (Lead Security Researcher)
Reviewed by
Nolan (CEO)
Closed
Case closed after final validation memo.