¿Por qué no debe usarse memcmp para comparar datos críticos de seguridad?

37

Desde man 3 memcmp :

  

No use memcmp() para comparar datos críticos de seguridad, como   secretos criptográficos, porque el tiempo de CPU requerido depende de la   Número de bytes iguales.          En su lugar, se requiere una función que realice comparaciones en tiempo constante.

¿Por qué es así? Mi pensamiento es que si alguien tiene acceso a la máquina que procesa estos "datos críticos de seguridad", estos secretos ya están comprometidos porque esa persona puede extraerlos de la RAM. O, si esa persona no tiene acceso a la máquina, de todos modos no puede medir con precisión el tiempo de CPU.

    
pregunta gaazkam 30.05.2017 - 18:33
fuente

3 respuestas

47

La explotación de la información de tiempo es un posible ataque contra cosas como los sistemas de autenticación de contraseña.

Conceptualmente memcmp() funciona comparando dos conjuntos de datos binarios en una base de byte a byte (en realidad, los procesadores pueden comparar varios bytes a la vez, dependiendo de las optimizaciones, pero se aplicarán los mismos principios a continuación). La función comienza al comienzo de los datos, compara cada byte de forma secuencial y sale tan pronto como encuentra una diferencia. Si no se encuentra ninguna diferencia, la función devuelve un código que indica que los datos coinciden.

Debido a que la función regresa tan pronto como encuentra una diferencia, un atacante con un reloj suficientemente preciso puede deducir información secreta. Pueden inducir llamadas a memcmp() con diferentes entradas y al medir qué entradas tardan más pueden deducir lo que podría ser un secreto almacenado.

Ejemplo :

Considere un sistema de hashing de contraseñas clásico. Supongamos que su contraseña se almacena como un hash secreto, por ejemplo, Ek8fAMjPhBo . (Ese hash se generó utilizando el esquema DES provisto por la función crypt() de Linux con una sal de na y una contraseña de secret . Tenga en cuenta que esta función es insegura y no debe usar en sistemas reales.)

En un sistema de contraseñas seguras, su hash Ek8fAMjPhBo está almacenado, pero su contraseña no está almacenada. Cuando se le solicite que autentique el sistema, tomará su contraseña, la modificará y luego comparará los dos hashes entre sí. Si los hashes resultantes coinciden, se le otorga acceso al sistema; si los hashes no coinciden, se rechazará su contraseña. Esto permite que el sistema verifique si conoce o no su contraseña sin almacenar realmente la contraseña.

Cómo un atacante puede usar la sincronización para atacar este sistema:

Para atacar este sistema, un adversario realmente necesita descubrir qué hash de contraseña para el hash almacenado. Normalmente, el hash almacenado se mantiene en secreto, pero el adversario puede usar la información de tiempo para deducir lo que podría ser el hash almacenado. Una vez que el adversario deduce el hash almacenado, es vulnerable a ataques rainbow table mucho más rápidos y fuera de línea, así como a evitar las medidas de seguridad en línea como los límites de reintento de contraseña.

El sistema de contraseñas anterior debe comparar un hash candidato con el hash almacenado para funcionar correctamente. Supongamos que se necesitan 10 nanosegundos para comparar cada byte del hash candidato con el hash almacenado secreto. Si no coinciden los bytes (una comparación), memcmp() tomará aproximadamente 10ns. Si un byte coincide (dos comparaciones), memcmp() tomará aproximadamente 20ns. Su atacante genera unas pocas contraseñas y las ejecuta a través del sistema, registrando cuánto tiempo toma cada una. Supongamos que las primeras comparaciones de hash toman aproximadamente 10 ns cada una y luego regresan, lo que indica que ninguno de los bytes del hash candidato coincide con el hash almacenado. Después de algunos intentos, una de las comparaciones de hash toma 20 ns, lo que indica que el primer byte del hash candidato coincide con el hash almacenado. En el ejemplo anterior, esto indica que el atacante ha deducido que el primer byte del hash Ek8fAMjPhBo es E .

Los hash por diseño tienen la propiedad de que no se puede predecir qué hash se corresponderá con qué contraseña, por lo que, por ejemplo, no le dice al atacante que la contraseña comienza con s . Sin embargo, el atacante podría tener una tabla grande de hash precalculados (una tabla de arco iris ) para que puedan buscar otras contraseñas que tengan un hash en una cadena que comienza con E . Después de que prueben suficientes hashes, finalmente obtendrán una entrada que hace que memcmp() tome 30ns, lo que indica que los primeros dos bytes coinciden, y han deducido que los primeros dos bytes del hash son Ek . Repiten este proceso una y otra vez hasta que deducen la totalidad o la mayor parte del hash. En ese momento, ya sea que conocen la contraseña o pueden usar la fuerza bruta con un ataque tradicional a la mesa del arco iris.

Esto es un poco hipotético, pero puedes encontrar mucha información práctica sobre cómo sincronizar ataques en cualquier otro lugar de la red, por ejemplo:

enlace

    
respondido por el David 30.05.2017 - 21:35
fuente
12

El asunto no es realmente argumentar que un ataque de canal lateral es práctico en cualquier aplicación que tengas en mente para tu sistema.

Un mejor punto para hacer es que

  1. Los ataques de canal lateral tienden a ser posibles en más situaciones de lo que la mayoría de los desarrolladores podrán pensar de forma inmediata.

  2. En cualquier situación dada, confiablemente convenciéndose a sí mismo de que no hay ninguna oportunidad de sincronizar los ataques es mucho más trabajo en el momento del desarrollo que simplemente utilizando un método de comparación seguro como SOP. Más trabajo significa tanto más costos como un mayor riesgo de equivocarse.

En pocas palabras, es fruta de baja altura. Tener una política de "nunca usar memcmp en datos críticos para la seguridad", es superior a la política de "está bien usar memcmp cuando sea seguro" en casi todos los parámetros que pueda imaginar.

Si, de manera extraordinaria, usted está en una situación en la que reduce una fracción de un microsegundo de tiempo de CPU de cada comparación no coincidente (que generalmente no es común ¡En primer lugar, el caso!) le ahorrará dinero suficiente para que valga la pena gastar un esfuerzo en un análisis de seguridad adecuado, luego tendrá un montón de documentos comerciales que prueban este hecho.

(Y aun así, solo leer cómics durante el tiempo que le tomaría hacer ese análisis mientras deja que la Ley de Moore haga el trabajo por usted probablemente le ahorrará esos microsegundos de CPU para usted igualmente).

    
respondido por el Henning Makholm 31.05.2017 - 12:15
fuente
9

Cae en una categoría de ataques de canal lateral (los mismos requisitos que para RSA, el tiempo de ejecución con clave privada debe ser constante).   Además, no es necesariamente que la RAM esté comprometida, las operaciones se pueden ejecutar en TEE (entorno de ejecución confiable).

    
respondido por el VovCA 30.05.2017 - 19:28
fuente

Lea otras preguntas en las etiquetas