Contraseñas OTP

/img/posts/otp.webp

Introducción

Las contraseñas tradicionales son fáciles de copiar. Una vez que un atacante consigue robar una válida, para el sistema resulta prácticamente imposible distinguir entre el propietario legítimo y quien la ha obtenido de forma fraudulenta.

En el artículo anterior vimos cómo los sistemas MFA intentan reducir este problema combinando varios factores independientes de autenticación.

Existen diferentes tecnologías para implementar MFA. Cada una aporta una solución diferente. Una de las más extendidas es el uso de contraseñas de un solo uso, más conocidas como OTP.

En este artículo veremos como funciona OTP y por qué millones de usuarios generan códigos temporales cada día desde sus teléfonos móviles sin ser plenamente conscientes de la tecnología que hay detrás.

El problema de las contraseñas

Las contraseñas convencionales tienen una característica que resulta tan útil como peligrosa: no cambian nunca. Si hoy utilizas una contraseña para acceder a un servicio, mañana volverás a utilizar exactamente la misma. Y la semana siguiente también.

Esto significa que cualquier persona que consiga obtener esa contraseña podrá reutilizarla tantas veces como quiera. Da igual que la haya descubierto mediante phishing, malware, una filtración de datos o simplemente observándote mientras la escribes. Una vez la conoce, dispone exactamente de la misma información que tu.

La debilidad no reside en la complejidad de la contraseña, sino en que sigue siendo válida después de haberla robado.

Llegados a este punto surge una idea aparentemente sencilla: si el problema es que una contraseña puede reutilizarse, ¿por qué no hacer que deje de ser válida después de utilizarla?.

Esa simple pregunta dio origen a uno de los mecanismos de autenticación más utilizados en la actualidad: las contraseñas OTP.

¿Qué es un contraseña OTP?

OTP son las siglas de One Time Password, o contraseña de un solo uso.

A diferencia de las contraseñas tradicionales, un OTP nace con fecha de caducidad. Su validez se limita a un intervalo de tiempo muy reducido (habitualmente unos 30 segundos) tras el cual deja de ser válido y es reemplazado automáticamente por un nuevo código.

Cuando el usuario intenta autenticarse, además de introducir su contraseña habitual debe proporcionar el OTP generado específicamente para ese momento. Aunque un atacante consiguiera interceptar ese código OTP, su utilidad desaparecerá en cuestión de segundos y la información robada dejará de tener valor casi inmediatamente.

Esta sencilla idea reduce considerablemente el riesgo asociado a la reutilización de credenciales.

Implementaciones OTP

Existen dos algoritmos estandarizados para generar contraseñas de un solo uso:

  • HOTP (HMAC-Based One-Time Password)
  • TOTP (Time-Based One-Time Password)

Ambos utilizan un secreto compartido entre el servidor y la aplicación autenticadora para generar el mismo código OTP de forma independiente.

OTP schema

Como ese secreto permanece constante, es necesario combinarlo con un segundo valor que cambie continuamente. Ese segundo valor es el que garantiza que cada OTP sea diferente al anterior. La única diferencia entre HOTP y TOTP es cuál es ese segundo valor.

HOTP

HOTP fue el primer algoritmo ampliamente adoptado para generar contraseñas de un solo uso. En este algoritmo, el segundo valor es un contador que mantienen sincronizado el servidor y la aplicación autenticadora.

Cada vez que el usuario se autentica, ambas partes utilizan el mismo secreto compartido y el valor actual del contador para calcular un nuevo OTP.

En términos conceptuales, puede representarse así:

HOTP = func(secreto_compartido, contador)

Una vez utilizado el código, el contador se incrementa y el OTP deja de ser válido.

El principal inconveniente de este sistema es que ambas partes deben mantener el contador perfectamente sincronizado. Si el contador del servidor y el de la aplicación dejan de coincidir, los códigos generados serán diferentes y la autenticación fallará hasta recuperar la sincronización.

TOTP

TOTP es una evolución de HOTP que sustituye el contador por el tiempo como mecanismo de sincronización. En lugar de incrementar un contador tras cada autenticación, tanto el servidor como la aplicación utilizan la hora actual (normalmente dividida en intervalos de 30 segundos) para generar el OTP.

Conceptualmente, el algoritmo puede representarse como:

TOTP = func(secreto_compartido, tiempo)

Mientras ambos dispositivos mantengan una hora razonablemente sincronizada, generarán exactamente el mismo código durante cada intervalo de tiempo.

Por este motivo, cuando observas aplicaciones como Google Authenticator mostrando una cuenta atrás, en realidad estás viendo el tiempo restante hasta que se genere el siguiente OTP.

Al eliminar la necesidad de sincronizar un contador, TOTP resulta mucho más robusto y práctico que HOTP, motivo por el que se ha convertido en el estándar de facto para la mayoría de sistemas de autenticación multifactor.

¿Por qué aparece un código QR?

En el apartado anterior hemos visto que tanto HOTP como TOTP necesitan un secreto compartido entre el servidor y la aplicación autenticadora para generar exactamente los mismos códigos OTP.

La siguiente pregunta es inevitable: ¿cuando se comparte ese secreto compartido?

La respuesta es el código QR que aparece cuando activamos la autenticación multifactor.

La mayoría de personas piensa que ese QR simplemente sirve para registrar el servicio en la aplicación autenticadora. Sin embargo, su verdadera función es transferir de forma cómoda toda la información necesaria para configurar el generador de OTP.

Entre esa información se encuentra:

  • El nombre del servicio.
  • El nombre de la cuenta.
  • El algoritmo utilizado (HOTP o TOTP).
  • Los parámetros necesarios para generar los códigos, como el intervalo de tiempo en TOTP.
  • Y, sobre todo, el secreto compartido.

Una vez escaneado el QR, la aplicación almacena ese secreto de forma local. A partir de ese momento, tanto el servidor como el teléfono poseen exactamente el mismo secreto y pueden generar de forma independiente los mismos códigos OTP.

Este detalle tiene una consecuencia muy importante.

El verdadero secreto no son los seis dígitos que aparecen cada treinta segundos en la pantalla del teléfono. Esos códigos son simplemente el resultado de aplicar el algoritmo correspondiente al secreto compartido y al valor de sincronización (contador en HOTP o tiempo en TOTP).

El auténtico secreto es el que contiene el código QR.

Por este motivo conviene proteger ese QR con el mismo cuidado que una contraseña. Cualquier persona que consiga una copia podrá configurar su propia aplicación autenticadora y generar exactamente los mismos códigos OTP que el usuario legítimo.

Y por el mismo motivo, conservar una copia segura del QR (o del secreto que contiene) puede resultar muy útil. Si cambiamos de teléfono, perdemos el dispositivo o necesitamos reinstalar la aplicación autenticadora, bastará con volver a importar ese secreto para recuperar todos los códigos sin tener que volver a configurar cada servicio.

Aplicaciones autenticadoras

La forma más habitual de utilizar OTP es mediante una aplicación autenticadora instalada en el teléfono móvil. Algunas de las más populares son:

Todas ellas son compatibles con el estándar TOTP, lo que les permite generar códigos válidos para miles de servicios diferentes.

Las principales diferencias entre unas y otras no se encuentran en el algoritmo utilizado, sino en las funcionalidades adicionales que ofrecen, como:

  • Copias de seguridad
  • Sincronización entre dispositivos
  • Protección mediante contraseña o biometría
  • Cifrado de la base de datos
  • Licencia de código abierto
  • Facilidad de uso

Personalmente Aegis es la que mas me gusta, y la que utilizo actualmente. Además de implementar el estándar TOTP, es un proyecto de código abierto, cifra localmente toda la información almacenada y permite realizar copias de seguridad cifradas. Para mí, esa combinación entre transparencia, seguridad y control resulta difícil de igualar.

Ventajas e inconvenientes de los OTP

Los sistemas OTP ofrecen numerosas ventajas frente a las contraseñas tradicionales. Entre ellas destacan:

  • Reducen significativamente el impacto del robo de credenciales.
  • Son sencillos de implementar tanto para los servicios como para los usuarios.
  • Están ampliamente estandarizados y son compatibles con prácticamente cualquier plataforma.
  • No requieren dispositivos específicos más allá de una aplicación autenticadora.
  • Añaden una segunda prueba de identidad sin modificar el mecanismo de autenticación existente.
  • Para la mayoría de usuarios resultan fáciles de utilizar y apenas añaden unos segundos al proceso de autenticación.

Sin embargo, OTP no resuelve todos los problemas de seguridad.

La principal limitación es que el usuario sigue participando activamente en el proceso de autenticación al tener que introducir un código manualmente. Como consecuencia, continúa siendo vulnerable frente a ataques de phishing en tiempo real. Un atacante podría crear una página que imite al servicio legítimo y convencer al usuario para que introduzca allí el OTP. Como estos códigos son válidos durante un breve intervalo de tiempo, el atacante podría reutilizarlo inmediatamente para completar la autenticación.

Tampoco elimina por completo el problema de la gestión de secretos. Tanto el servidor como la aplicación autenticadora deben compartir el mismo secreto criptográfico para poder generar y verificar los códigos OTP.

Por último, la pérdida del teléfono móvil o de las copias de seguridad puede dificultar considerablemente la recuperación de las cuentas protegidas si no se han configurado mecanismos de recuperación adicionales.

Precisamente para resolver estas limitaciones surgieron mecanismos de autenticación más modernos, como FIDO2, que eliminan la necesidad de compartir secretos y hacen que el phishing resulte mucho más difícil. Hablaremos sobre FIDO2 en un articulo posterior.

Conclusión

Los OTP representan uno de los avances más importantes en la evolución de los sistemas de autenticación.

Su idea fundamental es sorprendentemente sencilla: si una contraseña puede ser robada y reutilizada, hagamos que deje de ser válida casi inmediatamente.

Durante más de dos décadas, algoritmos como HOTP y, especialmente, TOTP han protegido millones de cuentas en todo el mundo y han demostrado que añadir un segundo factor de autenticación incrementa de forma muy significativa la seguridad frente al uso exclusivo de contraseñas.

Sin embargo, también hemos visto que OTP no elimina todos los problemas. El usuario sigue teniendo que introducir manualmente un código y el sistema continúa dependiendo de un secreto compartido entre el servidor y la aplicación autenticadora.

Hasta ahora hemos utilizado ese secreto compartido para generar códigos OTP. Pero ¿es posible aprovechar el mismo secreto para demostrar nuestra identidad sin necesidad de generar un código que el usuario tenga que escribir? La respuesta es que sí. Y precisamente esa es la idea que hay detrás de Challenge-Response.

En el próximo artículo exploraremos este mecanismo criptográfico, ampliamente utilizado por dispositivos como YubiKey, y veremos cómo permite demostrar la posesión de un secreto sin revelarlo nunca.

Si te gustan este tipo de artículos sobre seguridad, Linux, criptografía y sistemas, puedes seguir el canal de Telegram para no perderte los próximos artículos de esta serie. Allí publico cada nueva entrada en cuanto está disponible y comparto noticias, recursos y contenido relacionado con los temas que voy investigando.

Muchas gracias por acompañarme hasta aquí y, ¡nos vemos en el próximo articulo!.

Pulso la tecla ESC:wq!