Respuesta rápida
Un acortador de URLs corporativo, usado para enviar tickets de compra por SMS, tenía tres problemas que juntos se vuelven críticos: códigos de 6 caracteres con baja entropía, sin rate limiting, y página de destino sin autenticación. Un solo equipo a 15 req/s extraía PII (teléfono, BIN+últimos 4 de tarjeta, productos comprados) de ~300 personas por hora.
La cadena de fallos
Tres problemas independientes que al combinarse se vuelven críticos:
[Códigos 6 chars baja entropía]
↓
[Sin rate limiting en el acortador]
↓
[Página de ticket sin autenticación]
↓
[PII completa expuesta]
Fallo 1 — Códigos de baja entropía
Los códigos del acortador son cadenas de 6 caracteres alfanuméricos. El espacio teórico es grande, pero la densidad de códigos válidos activos en producción es suficientemente alta como para que la enumeración aleatoria devuelva resultados de forma consistente.
Fallo 2 — Sin rate limiting
El acortador no bloquea ni desafía peticiones en volumen desde una sola IP. A 15 req/s el servidor responde con normalidad. Sin CAPTCHA, sin throttling, sin 429. La enumeración puede correr indefinidamente.
Fallo 3 — Tickets sin autenticación (el fallo principal)
Las páginas de ticket destino muestran toda la información del cliente sin pedir ninguna verificación. Cualquiera con el enlace ve lo mismo que el cliente legítimo:
- Número de teléfono completo.
- Fecha y tienda física donde se realizó la compra.
- Lista de productos con precios.
- Importe total.
- Número parcial de tarjeta — BIN + últimos 4 dígitos (
435785******0916). - Código QR del ticket.
Cómo funciona el ataque
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
El teléfono viaja codificado en base64 directamente en la URL de redirección:
Location: https://target.tld/user-identification.html?phone=NjM0XXXXXXXX==&...
Esto significa que ni siquiera hace falta cargar la página del ticket para obtener el número de teléfono. Basta con leer el header Location.
El PoC, en una línea:
python3 bruteforce.py -r 15 -o hits.txt
Impacto
Smishing de alta credibilidad. El atacante conoce el teléfono, qué compró, en qué tienda y cuándo. Un SMS con esos datos exactos supera sin problemas los filtros cognitivos de cualquier víctima.
Fraude bancario. BIN + últimos 4 dígitos es suficiente para superar verificaciones de identidad básicas en muchas entidades si el atacante llama haciéndose pasar por el cliente.
Perfilado masivo. Correlacionando tickets por teléfono se construyen historiales de compra detallados de individuos concretos.
RGPD. Teléfonos, datos de tarjeta e historial de compras de clientes en la UE sin ninguna protección. Brecha notificable bajo el artículo 33.
Qué buscar en targets similares
Los acortadores corporativos son un vector que se suele ignorar. Cuando encuentres uno:
- ¿Cuántos caracteres tiene el código? ¿Qué alfabeto usa?
- ¿Hay rate limiting en el endpoint de resolución?
- ¿La URL de destino contiene parámetros sensibles? ¿Están en base64 (que no es cifrado)?
- ¿La página destino requiere autenticación o es accesible directamente?
- ¿Los enlaces tienen expiración?
El patrón acortador + página sensible sin auth aparece con frecuencia en sistemas de notificaciones transaccionales: tickets, facturas, confirmaciones de pedido, citas médicas.
Fix
| Punto | Solución |
|---|---|
| Páginas de ticket | Verificación de identidad antes de mostrar datos (OTP, últimos dígitos del teléfono) |
| Acortador | Rate limiting + detección de enumeración |
| Códigos cortos | Mayor entropía + expiración de enlaces |
| PII en URL | No exponer datos sensibles en parámetros de URL, ni en base64 |
Labs relacionados
Practica enumeración de short links y caza de páginas sensibles sin auth: labs de Information Disclosure.
Practica esto en un lab
Information Disclosure
Sigue aprendiendo · cuenta gratis
Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.
Artículos relacionados
Mass PII Extraction vía GraphQL — 93 perfiles reales en 1 hora
Un endpoint GraphQL de sincronización de contactos sin rate limiting, sin verificación de propiedad y con batching de 200 números por petición. Resolución teléfono → identidad real.
API keys expuestas en HTML público — $2.000 sin un solo bypass
Una plataforma de productividad entregaba un token de un CMS de terceros en window.CONFIG. Cualquiera con DevTools podía descargar templates de pago. Cómo cazar este patrón en cualquier app SPA.
0-click Account Takeover — OTP brute force + Email Normalization
Dos fallos por separado parecen menores. Juntos, te dan ATO completo conociendo solo el email. Bounty real: €560 y 12 minutos de explotación.