# Two-factor authentication bypass on Grab Android App

Grab Android profile-edit endpoint lacked rate limiting and code expiry, letting an attacker brute-force the 4-digit SMS 2FA code and take over accounts.

- Payout: hidden
- Severity: medium
- Program: Grab
- Found by: sp1d3rs
- Disclosed: 2017-09-12
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/202425
- Library page: https://bugbountylibrary.com/r/h1%3A202425
- Tags: area:mobile domain:api domain:mobile impact:ato kind:bounty platform:hackerone sev:medium technique:recon vuln:account-takeover vuln:auth-bypass vuln:mfa-bypass

**Target:** Mobile app REST API endpoint /api/passenger/v2/profiles/edit
**Root cause:** The profile-edit endpoint accepted the 4-digit SMS profileActivationCode with no rate limiting and no code expiration after failed attempts, allowing exhaustive enumeration of all 1000-9999 combinations.
**Steps:**
1. Log in to Grab Android app via Google with a valid phone number.
2. Edit profile name and Save; a 4-digit SMS code is sent.
3. Extract the `x-mts-ssid` session header from any app request via proxy.
4. Send `PUT /api/passenger/v2/profiles/edit` with `Content-Type: application/x-www-form-urlencoded` and body `profileActivationCode=3122`; wrong code returns `400 {"status":400,"code":4000}`, correct code returns `204 No Content`.
5. Brute-force all codes 1000-9999 with the C# tool until a 204 is returned.
**How found:** Noticed the profile-edit endpoint required a 4-digit SMS code and tested a wrong code, observing a distinct 400 vs 204 response, then reasoned that without rate limiting or expiry the small keyspace could be exhausted.
**Exploitation:** Attacker with a valid session (x-mts-ssid) iterates all 4-digit codes against the profile-edit endpoint; the correct code returns 204, completing the 2FA step and enabling account takeover (changing email/phone of victim).
**Escalation:** Researcher later escalated a similar OTP bypass on the 'Login with mobile number' endpoint to unauthenticated full account takeover in report #205000.
**Insight:** When a step-up auth flow uses a short numeric code, probe the specific endpoint that consumes it (not just the login endpoint) for rate limiting and expiry — a 400/204 status differential gives a clean brute-force oracle.

