security - vuelve - ¿Por qué la verificación de una contraseña incorrecta toma más tiempo que la correcta?
nombre de usuario o contraseña incorrecta (12)
Esta pregunta siempre me ha preocupado.
En Linux, cuando se le solicita una contraseña, si su entrada es la correcta, se verifica de inmediato, casi sin demora. Pero, por otro lado, si escribe la contraseña incorrecta, lleva más tiempo verificarla. ¿Porqué es eso?
Observé esto en todas las distribuciones de Linux que he probado.
Básicamente para mitigar la fuerza bruta y los ataques de diccionario.
De la Guía del desarrollador de la aplicación Linux-PAM :
Planificación de retrasos
extern int pam_fail_delay(pam_handle_t *pamh, unsigned int micro_sec);
Esta función es ofrecida por Linux-PAM para facilitar demoras después de una llamada fallida a pam_authenticate () y antes de que se devuelva el control a la aplicación. Al usar esta función, el programador de la aplicación debe verificar si está disponible con,
#ifdef PAM_FAIL_DELAY .... #endif /* PAM_FAIL_DELAY */
En general, una aplicación solicita que un usuario sea autenticado por Linux-PAM a través de una llamada a pam_authenticate () o pam_chauthtok (). Estas funciones llaman a cada uno de los módulos de autenticación apilados listados en el archivo de configuración de Linux-PAM relevante. Tal como lo indica este archivo, uno o más de los módulos pueden fallar, provocando que la llamada pam _... () devuelva un error. Es deseable que también haya una pausa antes de que la aplicación continúe. La razón principal de tal retraso es la seguridad: un retraso actúa para desalentar ataques de diccionario de fuerza bruta principalmente, pero también ayuda a obstaculizar los ataques programados (canal oculto).
En Ubuntu 9.10, y creo que también nuevas versiones, el archivo que está buscando se encuentra en
/etc/pam.d/login
edita la línea:
auth opcional pam_faildelay.so delay = 3000000
cambiando el número 3 con otro que desee.
Tenga en cuenta que para tener una autenticación ''nodelay'', CREO que debe editar el archivo
/etc/pam.d/common-auth
también. En la línea:
auth [success = 1 default = ignore] pam_unix.so nullok_secure
agregue ''nodelay'' a la final (sin comillas). Pero esta explicación final sobre el ''nodelay'' es lo que creo.
En realidad, es para evitar que los ataques de fuerza bruta intenten millones de contraseñas por segundo. La idea es limitar qué tan rápido se pueden verificar las contraseñas y hay una serie de reglas que se deben seguir.
- Un par de usuario / contraseña exitoso debería tener éxito inmediatamente.
- No debe haber una diferencia discernible en los motivos de falla que puedan detectarse.
Ese último es particularmente importante. Significa que no hay mensajes útiles como:
Your user name is correct but your password is wrong, please try again
o:
Sorry, password wasn''t long enough
Ni siquiera una diferencia de tiempo en respuesta entre los motivos de error "usuario no válido y contraseña" y "usuario válido pero contraseña no válida".
Cada falla debe entregar exactamente la misma información, textual y de otro tipo.
Algunos sistemas lo llevan aún más lejos, lo que aumenta la demora con cada falla, o solo permite tres fallas y luego tiene un retraso masivo antes de permitir un nuevo intento.
Es una forma muy simple, prácticamente sin esfuerzo de aumentar en gran medida la seguridad. Considerar:
El sistema
A
no tiene retraso. Un atacante tiene un programa que crea combinaciones de nombre de usuario / contraseña. A una velocidad de miles de intentos por minuto, solo lleva unas horas probar cada combinación y registrar todos los inicios de sesión exitosos.El sistema
B
genera un retraso de 5 segundos después de cada conjetura incorrecta. La eficacia del atacante se ha reducido a 12 intentos por minuto, lo que ha paralizado el ataque de fuerza bruta. En lugar de horas, puede llevar meses encontrar un inicio de sesión válido. Si los hackers fueran ese paciente, se volverían legítimos. :-)
Esto hace que tome más tiempo adivinar contraseñas.
Estoy de acuerdo. Esta es una decisión de programación arbitraria. Poner la demora en un segundo en lugar de tres en realidad no afecta la capacidad de crackear de la contraseña, pero la hace más fácil de usar.
Las demoras de autenticación fallidas están ahí para reducir la tasa de intentos de inicio de sesión. La idea de que si alguien intenta un diccionario o un ataque de fuerza bruta contra uno o cuentas de usuario puede requerir que el atacante aguarde el retraso de fallas y así lo obligue a tomar más tiempo y darle más oportunidad de detectarlo.
También podría estar interesado en saber que, dependiendo de lo que esté utilizando como shell de inicio de sesión, generalmente hay una forma de configurar este retraso.
En GDM, el retraso se establece en el archivo gdm.conf (generalmente en /etc/gdm/gdm.conf). necesita establecer RetryDelay = x donde x es un valor en segundos.
La mayor parte de la distribución de Linux de este día también admite la definición de FAIL_DELAY en /etc/login.defs, lo que le permite establecer un tiempo de espera después de un intento fallido de inicio de sesión.
Finalmente, PAM también le permite establecer un atributo nodelay en su línea de autenticación para eludir el retraso de fallas. ( Aquí hay un artículo sobre PAM y Linux )
Lo que intenté antes parecía funcionar, pero en realidad no; si te importa, debes revisar el historial de edición de wiki ...
Lo que funciona (para mí) es, tanto para disminuir el valor de pam_faildelay.so delay = X en /etc/pam.d/login (lo bajé a 500000, medio segundo), y también agregar nodelay (precedido por un espacio) al final de la línea en common-auth , según lo describe Gabriel en su respuesta.
auth [success=1 default=ignore] pam_unix.so nullok_secure nodelay
Al menos para mí (debian sid), solo hacer uno de estos cambios no acortará el retraso apreciablemente por debajo de los 3 segundos predeterminados, aunque es posible alargar el retraso cambiando solo el valor en /etc/pam.d/login.
¡Este tipo de basura es suficiente para hacer llorar a un hombre adulto!
Me gustaría agregar una nota desde la perspectiva de los desarrolladores. Aunque esto no sería obvio a simple vista, un desarrollador inteligente saldría de una consulta de coincidencia cuando se encuentre la coincidencia. En el testimonio, una partida exitosa se completaría más rápido que una partida fallida. Porque, la función de comparación compararía las credenciales con todas las cuentas conocidas hasta que encuentre la coincidencia correcta. En otras palabras, digamos que hay 1,000,000 cuentas de usuario en orden por IDs; 001, 002, 003 y así sucesivamente. Su ID es 43,001. Por lo tanto, cuando ingresa un nombre de usuario y una contraseña correctos, el escaneo se detiene en 43,001 y se registra. Si sus credenciales son incorrectas, entonces escanea todos los 1,000,000 de registros. La diferencia en el tiempo de procesamiento en un servidor de doble núcleo podría ser en milisegundos. En Windows Vista con 5 cuentas de usuario estaría en nanosegundos.
No estoy seguro, pero es bastante común integrar un retraso después de ingresar una contraseña incorrecta para hacer los ataques más difíciles. Esto hace que un ataque sea prácticamente inviable, ya que le tomará mucho tiempo verificar solo algunas contraseñas.
Incluso probar algunas contraseñas (fechas de nacimiento, el nombre del gato y cosas por el estilo) no se convierte en diversión.
No veo que pueda ser tan simple como sugieren las respuestas.
Si la respuesta a una contraseña correcta es (algún valor de) inmediata, ¿no solo tiene que esperar hasta más tiempo que ese valor para saber que la contraseña es incorrecta? (al menos saber probabilísticamente, lo cual está bien para propósitos de craqueo) Y de todos modos estarías ejecutando este ataque en paralelo ... ¿es esto todo un gran tapete de bienvenida de DoS?
Técnicamente, este retraso deliberado es para prevenir ataques como el "Ataque de linearización" (también hay otros ataques y razones) .
Para ilustrar el ataque, considere un programa (sin este retraso deliberado), que verifica una serie ingresada para ver si coincide con la serie correcta, que en este caso resulta ser " xyba " . Para mayor eficiencia, el programador decidió verificar un carácter a la vez y salir tan pronto como se encuentre un carácter incorrecto, antes de comenzar también se verifican las longitudes.
La longitud de serie correcta tardará más en procesarse que una longitud de serie incorrecta. Incluso mejor (para el atacante), un número de serie que tenga el primer carácter correcto tomará más tiempo que cualquiera que tenga un primer carácter incorrecto. Los pasos sucesivos en el tiempo de espera se deben a que cada vez que hay un ciclo más, la comparación se realiza en la entrada correcta.
- Entonces, el atacante puede seleccionar una cadena de cuatro caracteres y que la cadena que comienza con x toma más tiempo. (por trabajo de adivinar)
- El atacante puede fijar el carácter como x y variar el segundo carácter, en cuyo caso encontrarán que y tarda más.
- El atacante puede corregir los dos primeros caracteres como xy y variar el tercer carácter, en cuyo caso encontrará que b tarda más.
- El atacante puede corregir los tres primeros caracteres como xyb y variar el cuarto carácter, en cuyo caso descubrirá que a lleva más tiempo.
Por lo tanto, los atacantes pueden recuperar el personaje de serie a la vez.
Linearization.docx, salida de muestra
El número de serie tiene cuatro caracteres y cada personaje tiene 128 valores posibles. Luego hay 128 4 = 2 28 = 268,435,456 seriales posibles . Si el atacante debe adivinar aleatoriamente números de serie completos, ella adivinaría el número de serie en aproximadamente 2 27 = 134,217,728 intentos, lo cual es una enorme cantidad de trabajo . Por otro lado, al usar el ataque de linealización anterior, se requiere un promedio de solo 128/2 = 64 conjeturas para cada letra, para un trabajo total esperado de aproximadamente 4 * 64 = 2 8 = 256 conjeturas, que es una cantidad trivial de trabajo.
Gran parte del consejo de guerra escrito se adapta de this (tomado de la "Seguridad de la información: Principios y práctica" de Mark Stamp). Además, los cálculos anteriores no tienen en cuenta la cantidad de conjeturas necesarias para determinar la longitud de serie correcta.