Los códigos de un solo uso por SMS son el segundo factor más desplegado de internet y el más débil que sigue en uso masivo. El NIST desaconseja el SMS como autenticador restringido desde 2016, y sigue estando en todas partes porque es el único factor que prácticamente todos los usuarios ya tienen.
Si construyes u operas un flujo OTP, la pregunta práctica no es si el SMS es ideal. Es cómo operarlo para que los modos de fallo sean los que tú has elegido. Este artículo trata de diseño defensivo—no de eludir las protecciones de nadie.
El Modelo de Amenazas, en Breve
Diseña contra estos puntos concretos en lugar de contra "el fraude" en abstracto:
- SIM swap y secuestro de número — un atacante convence al operador de mover el número de la víctima a su dispositivo. Nada en tu flujo OTP detecta esto; solo ayudan las señales de recencia y las comprobaciones escalonadas.
- Phishing con retransmisión en tiempo real — un sitio proxy recoge el código de la víctima y lo reenvía dentro de su vida útil. Es el ataque dominante contra el OTP por SMS hoy, y la vida útil del código es tu principal palanca.
- Interceptación en un dispositivo comprometido — vistas previas de notificaciones, apps maliciosas con permiso de SMS, historiales sincronizados.
- Fuerza bruta y reutilización — adivinar un código de 6 dígitos o reutilizar uno capturado.
- Enumeración — usar el endpoint de OTP para descubrir qué números tienen cuenta.
- SMS pumping (fraude de tarificación) — un atacante genera envíos a rangos de tarifa premium de los que obtiene beneficio. Este te cuesta dinero directamente y suele pasar desapercibido hasta que llega la factura.
Limitación de Tasa Que Funciona de Verdad
La mayoría de limitaciones fallan porque se aplican en un solo eje y los atacantes rotan los demás.
Limita por varias claves a la vez. Por número de teléfono, por cuenta, por IP, por huella de dispositivo y globalmente por país de destino. Quien rote IPs seguirá chocando con el techo por número; quien rote números chocará con el techo por IP.
Aplica retardo progresivo, no un muro. Un backoff creciente—30 segundos, luego dos minutos, luego diez—degrada el rendimiento de un ataque automatizado sin bloquear a un usuario legítimo que simplemente se equivocó al teclear.
Pon un techo por país de destino. El SMS pumping se concentra en rangos concretos. Un límite de envíos por país, con alerta al acercarse, lo detecta antes de que se convierta en una factura grande.
Añade fricción ante anomalías, no ante volumen. Un CAPTCHA en cada petición enseña a los usuarios a ignorarlo. Un CAPTCHA cuando la puntuación de riesgo cruza un umbral conserva su valor como señal.
Separa el límite de envío del de verificación. Son ataques distintos. Los envíos cuestan dinero y habilitan el pumping; los intentos de verificación son fuerza bruta. Bloquea el código tras un número pequeño de intentos fallidos—cinco es un techo habitual—con independencia de cuántos envíos permitas.
Vida Útil del Código, Entropía y Vinculación
Códigos de vida corta. Minutos, no horas. La ventana es tu defensa principal contra el phishing con retransmisión: un código que caduca en cinco minutos da al atacante cinco minutos. Más corto es más seguro, pero bajar de unos dos minutos empieza a generar soporte por usuarios en rutas lentas.
Un solo uso, invalidado al reemitir. Cuando un usuario pide un código nuevo, el anterior debe morir de inmediato. Dejar códigos previos válidos multiplica la superficie de ataque sin beneficio alguno.
Seis dígitos como mínimo. Combinado con un tope de cinco intentos, seis dígitos deja la fuerza bruta fuera de alcance. Los códigos de cuatro dígitos son adivinables con un presupuesto de intentos generoso.
Vincula el código al contexto. Guarda para qué se emitió y verifícalo al canjearlo:
- La acción (registro vs inicio de sesión vs restablecimiento de contraseña vs confirmación de pago)
- La sesión o dispositivo que lo solicitó
- El número y la región normalizados en formato E.164
Vincular a la acción es lo más importante. Un código emitido para confirmar un cambio de correo no debería poder canjearse para autorizar una transferencia.
Di en el mensaje para qué es el código. "123456 es tu código para confirmar una transferencia de 400 $" le da a una víctima de phishing la oportunidad de notar la discrepancia. Seis dígitos sueltos no le dan nada.
UX de Entrega: De Dónde Salen los Tickets
Los usuarios viven el OTP en binario—funcionó, o el producto está roto. Y buena parte de esa percepción la fija la interfaz, no la entrega.
Fija la expectativa de espera. "Los códigos suelen llegar en 30 segundos" evita la espiral de reenvíos, que a su vez provoca limitación y empeora la entrega de verdad.
Bloquea el reenvío tras una cuenta atrás visible. Un botón atenuado con temporizador detiene el comportamiento que más perjudica al propio usuario.
No filtres la existencia de cuentas en los errores. "Si existe una cuenta para este número, hemos enviado un código" es la formulación estándar. Distinguir entre "no hay cuenta" y "código enviado" regala a los atacantes un oráculo de enumeración.
Admite pegar y autocompletar. Usa autocomplete="one-time-code" en el campo y el formato WebOTP vinculado al origen en el cuerpo del mensaje. Dividir el código en seis casillas que rechazan pegar es tanto un problema de usabilidad como de accesibilidad.
Ofrece una vía alternativa. Entrega por llamada de voz, correo, o una opción de dar de alta un autenticador. Algunas combinaciones de operador y región fallan en silencio, y un usuario sin alternativa simplemente se va.
Nunca muestres el número completo. Enmascara hasta los últimos dos a cuatro dígitos en cualquier pantalla de confirmación.
Instrumenta por Región y Operador
La tasa de entrega agregada es una cifra que oculta todos los problemas que merece la pena encontrar.
Registra envío correcto, acuse de entrega y verificación completada desglosados por país de destino y operador. Los cambios de enrutamiento aguas arriba aparecen como el colapso de una sola región mientras la media global apenas se mueve. Alerta sobre la desviación de cada segmento respecto de su propia línea base, no sobre la cifra global.
También vale la pena seguir la distribución del tiempo hasta verificar. Un p95 al alza suele indicar que una ruta se ha degradado antes de fallar del todo.
Retención de Datos: Guarda Menos
Conserva lo necesario para operar el soporte e investigar incidentes, y nada más:
- Guarda: marcas de tiempo, estado de entrega, país de destino, una referencia hasheada o truncada del número, y un rastro de auditoría de los resultados.
- No guardes: cuerpos de mensaje con códigos vivos más allá de la ventana de verificación. No hay motivo operativo y es un pasivo en cualquier brecha.
- Hashea los códigos en reposo. Un código en texto plano en una base de datos o un log es una exposición innecesaria. Registra su existencia, nunca su valor.
- Pon un TTL real. Los registros de verificación que persisten indefinidamente acumulan un conjunto de datos de números de teléfono que no pretendías construir.
Cómo lo gestiona USPhoneGen: Política de Privacidad · Términos de Servicio
Usuarios con Números Virtuales
Una parte significativa de tus usuarios verificará con números virtuales o de recepción en línea—por privacidad, por pruebas o porque están en el extranjero. Tu sistema debe seguir siendo seguro sin tratarlos como culpables por defecto.
Decide tu política de tipo de línea de forma deliberada, y decláralo. Si bloqueas números VoIP, dilo en el mensaje de error. Un genérico "la verificación ha fallado" ante un rechazo determinista por política lanza al usuario a un bucle de reintentos que jamás puede funcionar, y acaba en tu cola de soporte.
No penalices la latencia del operador. La variación regional es normal. Los tiempos de espera y la lógica de reintento deben acomodar rutas lentas en lugar de tratarlas como señal de fraude.
Pondera el tipo de línea como una entrada más. El historial del número, la reputación de la IP, las señales de dispositivo y la velocidad aportan información. Un bloqueo total de VoIP es un instrumento romo: correcto para un flujo de pago, y normalmente equivocado para un boletín.
Revalida en los momentos que importan, no continuamente. Volver a comprobar en una retirada de fondos o un cambio de credenciales es proporcionado. Recomprobar una cuenta inactiva y dejar al usuario fuera es la forma de perder a gente que no hizo nada malo.
Cómo funciona la clasificación de tipo de línea y por qué genera los rechazos que reportan tus usuarios: Non-VoIP vs VoIP
Planifica la Salida del SMS
El OTP por SMS es un suelo, no un destino. Diseña de forma que puedas mover a los usuarios fuera de él:
- Ofrece TOTP o passkeys junto al SMS y propón el alta tras un inicio de sesión exitoso, no durante el registro, donde la fricción cuesta conversión.
- Nunca dejes que el SMS anule en silencio un factor más fuerte. Si un usuario tiene una passkey, un SMS como respaldo incondicional reduce su seguridad a la del SMS.
- Trata los cambios de número como eventos de alto riesgo. Exige el factor existente e impón un periodo de enfriamiento antes de que el número nuevo pueda usarse para recuperación.
Preguntas Frecuentes
¿Cuánto debe durar un OTP?
De dos a diez minutos. Cinco es un valor por defecto razonable. Menos reduce la ventana de retransmisión; demasiado poco genera fallos en usuarios con rutas lentas.
¿Cuántos intentos de verificación debo permitir?
Alrededor de cinco por código, luego invalídalo y exige un nuevo envío. Registra además los intentos fallidos por cuenta para detectar adivinación distribuida.
¿Debo bloquear los números VoIP?
Depende de lo que pueda hacer la cuenta. Para pagos o cualquier cosa bajo obligaciones KYC, sí. Para un producto de consumo general, un bloqueo total cuesta usuarios legítimos—pondera el tipo de línea junto a otras señales.
¿Cuál es el control de mayor valor?
Limitación de tasa multidimensional con topes de envío por país. Aborda fuerza bruta, enumeración y fraude de tarificación a la vez.
¿Merece la pena desplegar OTP por SMS en 2026?
Como base para usuarios que no tienen otra cosa, sí. Como el factor más fuerte que ofreces, no. Despliégalo junto a un camino hacia TOTP o passkeys.
¿Cómo detengo el SMS pumping?
Topes de envío por país con alertas, bloqueo de rangos de destino que no atiendes y fricción progresiva en cuentas nuevas. Vigila el coste por usuario verificado desglosado por país—el pumping aparece ahí primero.
Referencias
- OWASP Authentication Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
- NIST SP 800-63B (Digital Identity Guidelines): https://pages.nist.gov/800-63-3/sp800-63b.html
Lectura Relacionada
- Guía de entrega para usuarios: Recibir SMS en Línea: Paso a Paso
- Patrones de aceptación por plataforma: ¿Qué Apps Aceptan Números Virtuales?
- Diagnóstico de entrega: Solución de Problemas OTP
