Intermediate levelFree

URL shortener as a mass PII leak — extraction of ~300 people/hour

Low-entropy codes + no rate limiting + a ticket with no auth = enumeration of phone numbers, cards (BIN+last 4) and real customers' purchases.

Gorka El BochiMay 9, 202611 min

Quick answer

A corporate URL shortener, used to send purchase receipts by SMS, had three problems that together become critical: 6-character codes with low entropy, no rate limiting, and a destination page with no authentication. A single machine at 15 req/s extracted PII (phone, BIN+last 4 of the card, purchased products) from ~300 people per hour.


The chain of flaws

Three independent problems that, when combined, become critical:

csharp
[Códigos 6 chars baja entropía]
        ↓
[Sin rate limiting en el acortador]
        ↓
[Página de ticket sin autenticación]
        ↓
[PII completa expuesta]

Flaw 1 — Low-entropy codes

The shortener's codes are 6-character alphanumeric strings. The theoretical space is large, but the density of valid codes active in production is high enough that random enumeration returns results consistently.

Flaw 2 — No rate limiting

The shortener doesn't block or challenge requests in volume from a single IP. At 15 req/s the server responds normally. No CAPTCHA, no throttling, no 429. Enumeration can run indefinitely.

Flaw 3 — Tickets with no authentication (the main flaw)

The destination ticket pages show all of the customer's information without asking for any verification. Anyone with the link sees the same as the legitimate customer:

  • Full phone number.
  • Date and physical store where the purchase was made.
  • List of products with prices.
  • Total amount.
  • Partial card number — BIN + last 4 digits (435785******0916).
  • Ticket QR code.

How the attack works

r
Generar código aleatorio de 6 chars
        ↓
GET acortador/{código}  (sin seguir redirección)
        ↓
¿HTTP 301/302/307?
   No  →  intentar otro código
   Sí  →  código válido
        ↓
Extraer header Location → URL del ticket con teléfono en base64
        ↓
Decodificar base64  →  teléfono obtenido sin cargar la página
        ↓
Cargar página del ticket (sin autenticación)
        ↓
PII completa expuesta

The phone travels encoded in base64 directly in the redirect URL:

ini
Location: https://target.tld/user-identification.html?phone=NjM0XXXXXXXX==&...

This means you don't even need to load the ticket page to obtain the phone number. Reading the Location header is enough.

The PoC, in one line:

bash
python3 bruteforce.py -r 15 -o hits.txt

Impact

High-credibility smishing. The attacker knows the phone, what was bought, at which store and when. An SMS with that exact data easily gets past any victim's cognitive filters.

Bank fraud. BIN + last 4 digits is enough to pass basic identity checks at many institutions if the attacker calls impersonating the customer.

Mass profiling. By correlating tickets by phone, detailed purchase histories of specific individuals are built.

GDPR. Phone numbers, card data and purchase history of EU customers without any protection. Notifiable breach under Article 33.


What to look for in similar targets

Corporate shorteners are a commonly overlooked vector. When you find one:

  • How many characters does the code have? Which alphabet does it use?
  • Is there rate limiting on the resolution endpoint?
  • Does the destination URL contain sensitive parameters? Are they in base64 (which is not encryption)?
  • Does the destination page require authentication or is it directly accessible?
  • Do the links have an expiration?

The pattern shortener + a sensitive page with no auth appears frequently in transactional notification systems: tickets, invoices, order confirmations, medical appointments.


Fix

PointSolution
Ticket pagesIdentity verification before showing data (OTP, last digits of the phone)
ShortenerRate limiting + enumeration detection
Short codesHigher entropy + link expiration
PII in the URLDon't expose sensitive data in URL parameters, nor in base64

Practice enumerating short links and hunting sensitive pages with no auth: Information Disclosure labs.

Practice this in a lab

Information Disclosure

Solve

Keep learning · free account

Save your progress, unlock advanced payloads and rank your flags.

Create account

Related articles

hunters training
711

hunters training

labs from real reports
55

labs from real reports

completions
1,205

completions

in bounties practiced
$213,970

in bounties practiced

46 flags captured this week·Real reports from HackerOne · Bugcrowd · Intigriti·No commitment·Free Academy