El atacante cuenta siempre con que el usuario medio presta poco interés en cuestiones de seguridad. A despecho de los avisos que emiten los administradores de sistema, muchas personas seguirán escogiendo contraseñas como password o 12345. Pero supongamos por un momento un mundo ideal en el que los usuarios utilizan contraseñas absolutamente aleatorias. Eso obligaría al atacante a olvidarse de los diccionarios de contraseñas y montar con un ataque de fuerza bruta, es decir, probar todas las posibilidades. Podría crear una tabla en la que, para cada valor posible del hash, se obtenga el texto llano correspondiente. Eso nos daría directamente la contraseña correspondiente a cualquier valor de hash.
Hasta hace relativamente poco, la mera idea de construir una tabla así era algo impensable en términos de espacio y de capacidad de cálculo. Tomemos, por ejemplo, la función de hash MD5. Convierte cualquier archivo en una cadena de 128 bits de longitud. Eso nos da un total de 2^128 posibles valores de hash, lo que excede a la capacidad de cálculo de todos los ordenadores del mundo combinados. Una tabla que contuviese cada valor del hash y de la contraseña correspondiente sería imposible de almacenar.
Afortunadamente, no es necesario llegar a tanto, porque se conocen procedimientos más sencillos. En 1980, el criptoanalista Martin Hellman propuso un compromiso (trade-off) entre tiempo y tamaño. En lugar de mirar una sola vez una tabla gigantesca, es posible utilizar tablas precalculadas más pequeñas, a expensas de un mayor tiempo de computación. Como ejemplo, postuló un sistema capaz de obtener la contraseña correspondiente al hash generado por el algoritmo DES (que, aunque es un algoritmo de cifra, también sirve como función hash). Según sus cálculos, una tabla de 10^13 bits conseguiría hacer el trabajo en aproximadamente un día[59]. El coste de construir una máquina así sería se estimó en varios millones de dólares. Pero eso fue en 1980. Desde entonces, la capacidad de cómputo de los ordenadores ha aumentado en un factor de un millón, y delante de mi ordenador tengo un disco duro capaz de albergar 10^13 bits (poco más de un TB) sin problemas.
Esas tablas precalculadas se conocen con el nombre de tablas rainbow o tablas arcoíris, y permiten acelerar enormemente el trabajo de encontrar una cadena alfanumérica conocida su función hash. Más correctamente, reduce el tamaño de las tablas que necesitamos para conseguirlo. La técnica de las tablas arcoíris no se limita a las funciones hash, ya que tiene aplicaciones criptográficas contra sistemas WiFi e incluso de telefonía móvil.
Por ahora, vamos a suponer que no hay sal en el guiso. Digamos que tenemos el hash 301B3C, correspondiente a la palabra en texto llano abcxyz (en lo que sigue, escribiré las contraseñas en minúscula y los hashes en mayúscula). Si tuviésemos una tabla con todos los posibles valores de hash, no habría más que buscar 301B3C y ver a qué contraseña corresponde. Pero no es posible fabricar una tabla tan grande, así que echaremos mano de un atajo.
Lo que vamos a hacer es definir una función matemática que nos relacione un valor de hash con una palabra determinada. La vamos a llamar función de reducción, y la representaremos con la letra R. Hasta cierto punto la función de reducción hace lo contrario que la función hash, pero mucho cuidado: H(a)=b no implica que R(b)=a. No son funciones inversas.
Las funciones R y H se utilizan para calcular lo que se denominan cadenas de hash. Vamos a crear los eslabones de la cadena mediante la aplicación de esas funciones, y luego guardarnos tan sólo los eslabones extremos. Por ejemplo, supongamos la siguiente cadena de cinco eslabones:
- Eslabón 1: aaaaaa
- Eslabón 2: H(aaaaaa)=KH28AQ
- Eslabón 3: R(KH28AQ)=uygwso
- Eslabón 4: H(uygwso)=301B3C
- Eslabón 5: R(301B3C)=abcxyz
De este modo creamos la cadena. A continuación, nos guardaremos los eslabones inicial y final (aaaaaa y abcxyz) y tiraremos el resto de los eslabones. Podemos ir repitiendo el mismo proceso para todos los eslabones iniciales que se nos ocurran. Los eslabones inicial y final de cada cadena formarán la tabla arcoíris. La columna de la izquierda representa las palabras de partida, que en nuestro caso representarán las posibles contraseñas; la de la derecha son el resultado de aplicar las funciones H y R un cierto número de veces:
aaaaaa abcxyz
aaaaab kzyqna
aaaaac fouqba
…
Fíjese el lector que la tabla arcoíris NO relaciona palabras con sus respectivos valores de hash. Esto es, H(aaaaaa) no es igual a abcxyz. Pero no importa, porque la tabla nos permitirá construir cadenas que nos revelen la información que buscamos.
Volvamos a nuestro problema inicial, a saber, ¿cuál es la palabra cuyo hash es 301B3C? Para descubrirlo, lo primero que hacemos es aplicarle la función de reducción, y obtenemos R(301B3C)=plskas. A continuación, miramos la tabla arcoíris y buscamos plskas en la segunda columna. No aparece. En ese caso damos de nuevo un pasito adelante y un pasito atrás: aplicamos la función hash H y de nuevo la función de reducción R:
H(plskas) = N986B1
R(N986B1) = series
De nuevo, miramos la tabla arcoíris y comprobamos si series está incluida en la columna de la derecha. Si no es así, damos otra vuelta a la manivela: H y después R. Llegará un momento en que el resultado sí estará en la tabla arcoíris. Digamos que en nuestro caso series sí está en la lista. Lo que he hemos hecho es construir la siguiente cadena:
301B3C --> plskas --> N986B1 --> series
Buscamos la entrada series en la columna de la derecha, y vemos que se corresponde con la entrada ooqksa en la columna de la izquierda de la tabla arcoíris. Eso NO significa que H(ooqksa)=series, ya que la tabla arcoíris no relaciona palabras con sus respectivos hashes. Lo que nos indica es que, partiendo de ooqksa, podemos construir una cadena que acabe en el hash que estamos considerando (301B3C). Bien, construyamos esa nueva cadena. No hay más que ir aplicando la función hash H y la función de reducción R hasta que aparezca el hash 301B3C. Puede ser algo de este estilo:
H(ooqksa) = KI32LA
R(KI32LA) = unidos
H(unidos) = 301B3C
De esa forma, hemos creado una segunda cadena. Y ya lo hemos conseguido. Fíjense en el último eslabón de la cadena. Nos dice que, aplicando la función hash a la palabra unidos, obtenemos el hash que estábamos buscando: H(unidos)=301B3C. Eso significa que la contraseña que buscábamos era unidos.
Es posible que usted, lector, considere que esta forma de obtener contraseñas partiendo del hash es algo compleja. Hasta cierto punto lo es, y eso que he simplificado el proceso (por ejemplo, en la práctica no se utiliza una función de reducción R, sino varias). Sin embargo, esto nos permite reducir mucho el tamaño de las tablas de búsqueda. Como contrapartida, cada proceso de búsqueda deberá calcular varias veces las funciones H y R. Es un compromiso entre espacio y tiempo [60].
En cierto modo, es como si usted quisiera encontrar un documento en un gran edificio administrativo. Usted no sabe dónde está su documento, así que entra en un despacho y pregunta. No saben responderle con precisión, pero le dirigen con un “vaya a la cuarta planta, despacho 42, y pregunte allí”. En dicho despacho tampoco saben nada, así que le indican otra dirección. De ese modo, subiendo y bajando pisos, abriendo y cerrando despachos, finalmente consigue usted encontrar lo que desea. Por supuesto, hubiera sido más fácil para usted si le hubieran indicado correctamente al principio, pero el tamaño del cartel necesario para indicar la posición de todos los documentos habría sido demasiado grande.
Una de las limitaciones de la tabla arcoíris es que está calculada para un conjunto grande pero limitado de contraseñas. Eso significa que no hay garantía absoluta de que funcione en un caso general, pero proporciona unas probabilidades de éxito muy altas. Por ejemplo, el programa para reventar contraseñas ophcrack dispone de diversas tablas arcoíris. La más grande de ellas (135 GB) puede revelar una contraseña de Windows Vista de hasta ocho caracteres alfanuméricos (letras minúsculas, mayúsculas y números) con una probabilidad de éxito del 99%[61]. Las tablas del RainbowCrack Project, son todavía mayores, de hasta 864 GB, y son válidas para las contraseñas procesadas mediante funciones de hash como MD5, así como para las de los sistemas operativos Windows 2000, XP, Vista y 7[62].
Otros proyectos, como los de Free Rainbow Tables, se basan en la participación de miles de colaboradores que donan su tiempo de cálculo[63]. Los chicos de Password Crackers no solamente le proporcionan gratuitamente los enlaces torrent a las tablas que usted desee, sino que le venden un disco duro con las tablas ya copiadas; la mayor de ellas ocupa 460 GB, de modo que no es mala idea de negocio[64].
Hay incluso servicios online para auditores de seguridad, como el ofrecido por Cryptohaze, que hace innecesario descargar las enormes tablas arcoíris. El software necesario ha sido liberado y se encuentra disponible en Internet[65]. En julio de 2012, su creador montó un sistema de computación compuesto por 31 chips GPU, utilizados normalmente en la tarjeta gráfica que controla el monitor de un ordenador, con el que logró comprobar valores hash a la increíble velocidad de 154 000 000 000 hashes por segundo[66]. A esa velocidad, podría descifrar un mensaje cifrado con el algoritmo DES en un día.
Afortunadamente, hay defensa contra los ataques de tablas arcoíris. El más sencillo es, nuevamente, utilizar sal. Si una función hash toma la contraseña del usuario y un valor único de sal para éste, el uso de tablas precomputadas es inútil, a no ser que el atacante se tome la molestia de calcular una tabla arcoíris distinta para cada valor de sal. Una de las ventajas de la sal en este tipo de aplicaciones es que no necesita guardarse en secreto, así que se suele almacenar junto al valor hash.
Atacar un sistema con hash y sal ciertamente no es un trabajo de media tarde; pero su implementación en un algoritmo de cifrado ampliamente usado hace que el número de objetivos potenciales sea enorme, y por tanto puede valer la pena el esfuerzo extra. Las tablas arcoíris disponibles en Internet, hasta donde yo sé, no incluyen valores de sal alguno; y dudo que lo hagan en el futuro, ya que las implementaciones actuales de muchos sistemas de seguridad utilizan sal de 48 a 128 bits de tamaño, lo que reduce a cero la utilidad de las tablas arcoíris. Eso sí, mientras haya sistemas que se nieguen a utilizar el sencillo truco de la sal, seguiremos viendo casos de intrusiones informáticas masivas como los que hemos visto en LinkedIn, Stratfor o PlayStation Network.
Pero incluso el uso de “sal de grano grueso” es inútil contra un ataque de diccionario. Si los usuarios emplean contraseñas fáciles de adivinar, o si éstas son demasiado cortas, un atacante puede tomarse el esfuerzo de aplicarles todos los valores posibles de sal, y tarde o temprano conseguir el premio. Eso sí, un usuario más comprometido con la seguridad que escoja una contraseña difícil de averiguar, estará protegido. Por desgracia, todavía proliferan los usuarios que piensan que 12345 es una contraseña segura. Veamos algunos ejemplos.