Unauth IDOR Leaks Live Prepaid Mobile Plan Purchase Records
The Risk
Anyone on the internet could watch the carrier's prepaid customers buy plans in real time. The system handed out purchase reference numbers as predictable counters, and the page that showed "your purchase succeeded" did not check who was asking. By stepping through the numbers an attacker could read every customer's phone number, the exact plan they just bought, the exact amount, and whether they had stored their bank card for automatic top-up. A single attacker could pull thousands of paying customers per day, then text each one with a perfectly-crafted phishing message within seconds of their checkout.
The Vulnerability
Two endpoints on the prepaid backend required no authentication:
GET /payments/issue-keyissued the next value of a single, globally shared, monotonically incrementing counterGET /payments/status?key=<KEY>returned the full purchase record bound to that key
Neither call required a cookie, an authorization header, a CSRF token, or an IP allowlist. The status endpoint did no ownership check on the key. By polling the issuer and querying every value behind the live counter, an attacker reads every paying customer's purchase record on the platform.
The key format was T + a six-digit date + an eight-digit counter that incremented by one per call. Five consecutive anonymous calls returned ...8249, ...8250, ...8251, ...8252, ...8253. The counter was shared across all customers and across two brand subscriber bases that fronted the same backend.
The Attack
All testing avoided retaining third-party PII. Three independent in-flight customer purchases were captured to prove cross-customer reach, with identifying values redacted in the public artefacts and only the per-record schema described below.
Step 1: confirm the issuer is anonymous
curl -sk 'https://target/prepaid/payments/issue-key'
{"key":"KEY-EXAMPLE-B"} Step 2: query a key below the live counter
curl -sk 'https://target/prepaid/payments/status?key=KEY-EXAMPLE-A' The response returned the full purchase record: paying customer's phone number, internal subscription identifier, brand, plan name, exact amount in local currency, payment status, wallet credit applied, automatic-renewal flag, and automatic-payment flag. A negative control with a future, not-yet-issued key returned "status":"UNUSED", confirming the backend reads the live transaction database on every request.
Step 3: measured rate of leak
Two anonymous calls 60 seconds apart showed the counter advance by 18 to 23 keys per minute (real production traffic, varying by time of day). Of 25 sequential keys probed in a sweep, 15 to 17 returned a used status with full purchase records (around 60 to 68 percent). Projected: thousands of customer purchase records leakable per day, anonymously.
Step 4: cross-brand reach
The internal subscription identifier prefix in the leaked records distinguished two carrier brands. Both brands shared the same key counter and the same status endpoint. A single unauthenticated sweep captured both brands' customer purchases.
The Impact
Per record exposed: paying customer's live phone number, brand, exact plan being purchased, exact amount, current purchase status (in-flight or completed), wallet usage, and recurring-billing flags.
Real attack scenarios
- Mass real-time harvest. A sweeper running against the predictable counter captures thousands of customer purchase records per day, building a real-time view of every paying prepaid customer across two brands
- Highly targeted phishing. With the exact phone number, exact plan name, and exact amount of an in-flight purchase, an attacker sends an SMS within seconds of checkout: "Your <amount> recharge is failing, click here to retry: <phishing URL>". The customer sees details that match exactly what they just did and trusts the message
- Stored-payment targeting. The automatic-renewal and automatic-payment flags are leaked alongside the phone number, building a ready-made list of customers with stored payment methods for targeted fraud
- Travel-pattern profiling. Plan names reveal when a customer is buying overseas roaming packs (for example, regional 24-hour data, country-specific travel data). The attacker knows the customer is travelling, when, and where, in real time
- Competitive intelligence. A competing carrier could continuously harvest purchase volumes by hour and plan to estimate revenue and identify popular products
- No customer-side mitigation. The leak is server-side. The customer cannot detect or prevent it; nothing they do influences their exposure
Why critical, not high
The leak is unauthenticated, mass-enumerable, real-time, and covers two brand customer bases in a single sweep. The fields exposed (phone number combined with order history) are a direct match for the program's listed critical scenario of mass customer data exposure including phone numbers and order history. The real-time weaponisation angle (phishing within seconds of checkout) moves the impact past "data leak" into active fraud enablement. Phone numbers in the country are regulated personal data under the territory's data privacy ordinance.
Remediation
- Bind every purchase key to the issuing session at creation. The status endpoint must verify the requesting session owns the key and reject all other queries
- Replace the sequential counter with an unguessable identifier: a 128-bit random UUID, or an HMAC-signed token tied to the user session and a short expiry. The current date-plus-sequence format is enumerable by design
- Require authentication on both the key issuer and the status endpoint. Neither has a legitimate anonymous use case
- Log and alert on out-of-pattern access. Any client that queries the status endpoint for keys it did not receive from the issuer in the same session is an attacker
- Interim mitigation while remediation is rolled out: per-IP rate limiting on the status endpoint (legitimate use is one or two calls per checkout, not thousands), and reject queries for keys older than a few minutes