2012-05-14 10 views
24

Acabo de encontrar este código en la biblioteca HTTP Auth del Zend Framework. Parece estar usando una función especial de comparación de cadenas para hacerlo más seguro. Sin embargo, no entiendo muy bien los comentarios. ¿Alguien podría explicar por qué esta función es más segura que haciendo $a == $b?Función de comparación segura de cadenas

/** 
* Securely compare two strings for equality while avoided C level memcmp() 
* optimisations capable of leaking timing information useful to an attacker 
* attempting to iteratively guess the unknown string (e.g. password) being 
* compared against. 
* 
* @param string $a 
* @param string $b 
* @return bool 
*/ 
protected function _secureStringCompare($a, $b) 
{ 
    if (strlen($a) !== strlen($b)) { 
     return false; 
    } 
    $result = 0; 
    for ($i = 0; $i < strlen($a); $i++) { 
     $result |= ord($a[$i])^ord($b[$i]); 
    } 
    return $result == 0; 
} 
+0

Esto es lo que 'hash_equals' hace en PHP 5.6+ – caw

Respuesta

36

Parece que están tratando de evitar timing attacks.

En criptografía, un ataque de temporización es un ataque de canal lateral en el que el atacante intenta comprometer un criptosistema mediante el análisis del tiempo necesario para ejecutar algoritmos criptográficos. Cada operación lógica en una computadora toma tiempo para ejecutarse, y el tiempo puede variar según la entrada; con mediciones precisas del tiempo para cada operación, un atacante puede retroceder hacia la entrada.

Básicamente, si se necesita una cantidad de tiempo diferente para comparar una contraseña correcta y una contraseña incorrecta, puede usar el tiempo para calcular cuántos caracteres de la contraseña ha adivinado correctamente.

considerar una comparación de cadenas muy deficiente (esto es, básicamente, la función normal igualdad de cadenas, con una obvia wait añadido):

function compare(a, b) { 
    if(len(a) !== len(b)) { 
     return false; 
    } 
    for(i = 0; i < len(a); ++i) { 
     if(a[i] !== b[i]) { 
      return false; 
     } 
     wait(10); // wait 10 ms 
    } 
    return true; 
} 

Digamos que da una contraseña y que (constantemente) realiza una cierta cantidad de tiempo para una contraseña, y aproximadamente 10 ms más para otra. ¿Qué te dice esto? Significa que la segunda contraseña tiene un carácter más correcto que el primero.

Esto le permite hacer piratería de películas, donde adivina una contraseña de uno en uno (lo cual es mucho más fácil que adivinar todas y cada una de las posibles contraseñas).

En el mundo real, hay otros factores involucrados, por lo que debe probar una contraseña muchas veces para manejar la aleatoriedad del mundo real, pero aún puede probar la contraseña de cada uno hasta que, obviamente, tome más tiempo luego, inicie con la contraseña de dos caracteres, y así sucesivamente.

Esta función tiene todavía un problema menor aquí:

if(strlen($a) !== strlen($b)) { 
    return false; 
} 

Le permite utilizar ataques de temporización de averiguar la longitud correcta de la contraseña, que le permite adivinar las contraseñas se moleste cualquier cortos o más largos. En general, you want to hash your passwords primero (que creará cadenas de igual longitud), así que supongo que no lo consideraron un problema.

+1

de hecho. "No vayas allí porque es peligroso, pero ve allí de todos modos, porque es el único camino" –

+1

Interesante, pero totalmente incorrecto. – rook

+0

@rook: ¿por qué está en lo correcto? De los comentarios en el código, eso es lo que Zend está tratando de lograr. – iWantSimpleLife

Cuestiones relacionadas