Prueba Nula: El hash no coincide.

Como buen gallego que soy, quiero compartir con vosotros la receta para cocinar un buen hash a la Gallega.

Si nunca habéis saboreado un hash, solo os diré que su sabor es único, no hay dos iguales. Una vez cocinado, no hay forma de volver atrás para averiguar cuales eran sus ingredientes. Lo que viene a significar para los más técnicos: una función determinista de un solo sentido y resumen.

Para esta receta, lo primero que necesitaremos es una cucharada de bytes recién cosechados. Los podemos comprar en nuestro supermercado de confianza, en la sección de: documentos de texto, fotografías, palabras o incluso imágenes forenses. Esta será la base para nuestra receta de hoy.

Fig 1. Otra buena receta, el pulpo a la gallega.

A continuación, cogeremos nuestros documentos de texto, fotografías… y los cortaremos muy finitos, en trocitos de 1 bit.

Si nos hemos quedado cortos con la cantidad de bits, le podremos añadir un “padding” o relleno, hasta que lleguemos a un número que dividido por 512 nos dé un resto de 448. Si ya tenemos este número antes de empezar, le echaremos otros 512 bits más al recipiente. Los bits que le añadamos tienen que ser de denominación de origen, es decir, de los que empiezan por 1 y luego se van rellenando con 0 hasta que se cumpla la condición anterior.

Ahora cogeremos el bote de los bits little-endian, y le echaremos dos puñados de 32 bits, hasta que lleguemos a los 64 bits.

Le añadimos a la mezcla anterior otras 4 palabras de 32 bits (en hexadecimal) que harán de base. La primera palabra que le echaremos es: 01 23 45 67, la segunda: 89 ab cd ef, la tercera: fe dc ba 98 y finalmente la última: 76 54 32 10.

Ahora volcamos el contenido del recipiente en la sartén y ya podemos comenzar a remover todo con los operadores XOR, OR, AND… mientras se va cocinando  a fuego lento. El truco para un hash consistente está en remover de forma adecuada todas las palabras hasta conseguir una mezcla homogénea de 32 caracteres hexadecimales, que será nuestro hash perfectamente cocinado.

Fig 2 Función hash

Si después de leer la receta del Hash a la gallega no sabes ni por dónde empezar, no te preocupes, por suerte para ti, al igual que para cocinar recetas de toda la vida han inventado la Thermomix, para calcular hashes de ficheros, también hace años que han inventado programas como HashCalc (para Windows) o md5sum / sha1sum… (para Linux) que te calculan los hashes de ficheros a golpe de clic en el ratón.

Ahora que ya sois unos expertos en elaborar un rico hash a la Gallega, ya sea de forma manual o automática, podemos pasar a la siguiente fase de la receta. Realmente la idea de este artículo no es explicar como opera una función hash, pues tampoco es necesario entender este algoritmo a tan bajo nivel, pero si me gustaría explicar, o por lo menos intentarlo, cuales son las casuísticas más comunes que se nos pueden dar a la hora de operar con hashes de firma digital. Después de unos cuantos años trabajado en esto de la informática forense, he visto que siempre se dan una serie de dudas recurrentes o falsos mitos sobre los hashes y su funcionamiento. Mi idea es tratar de desmitificar algunas de estas ideas y también exponer, desde un punto de vista distinto, argumentos que nos  permitan tener una visión un poco más amplia sobre el tema de las firmas digitales con hashes criptográficos.

1.) “No se puede cambiar el nombre del fichero”: Una de las falsas creencias que más he detectado en el tema de hashes de ficheros es la de que, si se cambia el nombre de un fichero, el hash del fichero también cambiará. Esto no es así: el hash se calcula sobre el contenido del fichero y no sobre el nombre de este. Por ejemplo, en un sistema de archivos tipo NTFS existe un tabla o índice en la que se especifican por su nombre todos los ficheros almacenados en ese disco duro y ya en el resto de la partición se van guardando los distintos ficheros. Un símil rápido es el del disco duro y el libro: imaginemos un libro que tiene un índice de todos los capítulos, realmente la novela está escrita en las páginas de cada capítulo, el índice del libro solo nos indica en que página estará posicionado cada capítulo dentro del libro.

 Con los discos duros ocurre exactamente lo mismo: en cada disco (partición realmente) existe un índice que contiene el nombre de todos los ficheros que hay guardados en la partición y el lugar que cada fichero ocupa dentro de la partición (como los capítulos). Por lo tanto tenemos dos cosas distintas, la primera es el nombre del fichero y está solo en el índice, la segunda es el fichero en sí y está almacenado en los distintos clusters del disco duro; y de estos últimos es de donde se calcula el hash, por lo que se puede cambiar el nombre del fichero, que no afectará a la parte en la que el fichero está guardado, ya que las direcciones seguirán siendo las mismas y por supuesto el contenido del fichero. Es como si el disco duro estuviera divido en dos partes: la primera la parte del índice, con el nombre de los ficheros, y la segunda la parte en la que se almacenan realmente lo ficheros. Es importante tener en cuenta que, si ese fichero se copia de un disco a otro, si la copia se ha realizado correctamente, se puede copiar miles de veces a miles de dispositivos distintos, que el hash seguirá siendo el mismo.

Si no creéis lo que digo, una imagen vale más que mil palabras. En la siguiente imagen se puede observar como un fichero tipo .txt que contiene la palabra “hola“, se renombra de “demo1.txt” a “demo1_nombre_cambiado.txt” sin cambiar su contenido, y este fichero sigue arrojando el mismo hash tipo SHA-1: 63bbfea… (¿¡¿¡fea?!?!)

Fig 3. Hash del mismo fichero con distinto nombre.

2.) “Se puede calcular el hash de una carpeta”: Si alguien lo ha intentado y lo ha conseguido, que me explique cómo lo ha hecho ¡que yo nunca lo consigo! (en sistemas NTFS, claro). Al igual que el caso anterior, una carpeta en un disco duro realmente “no existe” como tal, es simplemente una ruta en la tabla de índices del disco. Lo que si existe son los ficheros que la carpeta puede contener, por lo tanto, a una carpeta no se le puede calcular un hash, como demuestra la siguiente captura:

Fig 4. Hash de una carpeta

Otra cosa distinta es calcular el hash de todos los ficheros que se encuentren “dentro” de la carpeta, que si se puede hacer. Una excepción a este planteamiento son los ficheros .txt, los cuales si están vacíos “tampoco existen” en el espacio del disco duro, solamente existen en el índice de ficheros, y solo cuando se escriba al menos un byte en el .txt,  pasará a ser un fichero almacenado en el resto de espacio del disco duro. Por eso, cuando por ejemplo calculamos el hash de un fichero de texto vacío, siempre nos dá el hash: “da39a3ee5e6b4b0d3255bfef95601890afd80709”, como se puede ver a continuación, un fichero de texto completamente vacío no contiene ni un solo bit.

Fig 5. Visor hexadecimal de un fichero vacío. 

Y si tratamos de calcular un hash, por ejemplo SHA-1 de este fichero vacío, siempre nos dará el valor: “da39a3…”

Fig 6. Hash de un fichero de texto vacío.

 Esto no ocurre para el resto de ficheros ofimáticos (doc, docx, odt…), ya que, aunque estén vacíos (sin nada escrito), por defecto contienen una serie de información necesaria para su funcionamiento, como así se puede apreciar a continuación:

Fig 7. Visor hexadecimal de un documento ofimático “vacío”. 

3.) “El hash no tiene en cuenta los bits cero”: Como explicaba en el punto anterior, una cosa es un fichero de texto vacío, es decir, que “no existe” en disco, y otra cosa es un fichero formado por “n” ceros. Esto quizás se entienda mejor hablando de discos duros físicos o particiones lógicas: un disco duro puede estar vacío completamente, es decir, sin ningún tipo de fichero en su interior, pero esto no quiere decir que no tenga nada en su interior, al contrario, por definición un disco duro magnético siempre tendrá los mismos bits, eso sí, estos bits pueden estar en una u otra posición, que puede ser norte o sur, negativo o positivo, cero o uno… Por lo tanto el disco siempre estará “lleno” de bits, tantos como espacio tenga el disco. Lógicamente estos bits podrán ser todos cero, pero el cero ya es un valor, y por lo tanto tiene capacidad para interferir en el cálculo del hash. Por ejemplo, no es lo mismo el hash MD5 de “00” (cero, cero) que es “b4b147bc522828731f1a016bfa72c073 ” que el de “0000” (cuatro ceros) que es “4a7d1ed414474e4033ac29ccb8653d9b”. Como veis los bits cero se tienen en cuenta a la hora de calcular un hash, y esto es muy importante sobre todo a la hora de trabajar con imágenes forenses o clonados de disco duro.

Con el comando “dd” en Linux e indicando como origen de datos: “/dev/zero/” podemos crear imágenes forenses que su único contenido sean ceros, si esta imagen la abrimos con un editor hexadecimal, podremos comprobar que efectivamente su único contenido son bits cero:

Fig 8. Visor hexadecimal de un imagen forense con todos los bits a cero 

En función del tamaño que tenga esa imagen forense llena de ceros, si tratamos de calcularle un hash, veremos que el valor de esta cambiará en función del número de bits “cero” que contenga esta imagen. En la siguiente captura se observa que para la primera imagen forense de unos 197 MB de ceros, el valor hash es “cb7c1…”, sin embargo para la segunda imagen, que su tamaño es inferior, pero que también solo contiene ceros, su valor hash cambia completamente.

Fig 9. Hash de dos discos duros que solo contienen ceros.

4.) No pasa nada por abrir un fichero al que se le ha calculado un hash: La respuesta es depende, si es un fichero ofimático tipo .doc .docx .odt… es muy probable que con el simple hecho de abrirlo se pueda modificar, ya que si el programa que lo abre está configurado para realizar  guardados del fichero de forma automática, puede ocurrir que aunque nosotros no pulsemos el botón guardar, ya lo haga el programa por nosotros, modificándose de este modo el fichero y por consiguiente el hash del mismo. A continuación se muestra como se altera el hash de un fichero ofimático con tan solo abrirlo y cerrarlo.

Fig 10. Alteración del hash de un fichero ofimático solo por abrirlo.

En otro tipo de ficheros no pasa nada por visualizarlos, aunque lo recomendable es hacerlo siempre con un bloqueador de escritura, que impide que se guarden los cambios en el fichero y por lo tanto la integridad de este no se verá alterada.

5.) Si se hace una pequeña modificación en un fichero de texto el hash apenas varía: Esto tampoco es cierto, si habéis seguido la receta, en una parte se explica como el hash se va formando en base a unas palabras que van rotando. Esto implica que, aunque se realice la más mínima modificación, casi imperceptible en un fichero (aunque solo sea un bit), el hash resultante cambiaría totalmente. No es que cambie un par de números del hash, es que cambiará completamente el resultado. En el siguiente ejemplo se ve como, solo al cambiar un “6” por un “7” en un documento de texto, el hash del mismo ya cambia drásticamente.

Fig 11. Alteración de un hash por la modificación de un solo byte

Esto puede ser un grave problema en clonados de disco duro, ya que el hash se calcula directamente sobre el valor de los bits grabados físicamente en el disco, por lo que, si en un disco por el motivo que sea falla un solo bit de un plato por una avería o por un daño fortuito, el hash de este disco cambiará completamente. Por eso que si a veces en un hash falla un solo número o letra, la razón suele ser una mala transcripción del mismo y no una alteración del fichero que originó el hash.  Otra historia distinta serán las colisiones de hashes, tan de moda últimamente.

6.) Es mejor utilizar hashes tipo SHA-512 para evitar colisiones: Una colisión es básicamente cuando dos ficheros distintos arrojan el mismo número de hash, lo que implicaría un problema a la hora de garantizar la integridad de una evidencia digital. Antiguamente, se utilizaban hashes tipo MD5 para firmar digitalmente ficheros (OJO! No confundir con los ataques de colisión a sistemas de cifrado de contraseñas con MD5), pero al aumentar las capacidades de computo de los ordenadores, se logró que al calcular un hash MD5 a dos ficheros a priorí distintos, estos arrojaran el mismo número hash (una colisión). Las colisiones de MD5 fueron uno de los motivos que llevaron a utilizar mayoritariamente otro algortimo de hash más resistente a estas. Este fue el hash tipo SHA-1, al que también se le ha descubierto recientemente una colisión (pero no para firmado de documentos). Esto hace que nos venga a la mente una pregunta ¿Por qué no utilizar entonces un sistema de hash mucho más robusto como el SHA-512?. La razón es sencilla: por eficiencia. Ejemplo: calcular el hash SHA1 de un fichero de 1Tb puede tardar alrededor de 5 horas (lógicamente, en función del equipo a utilizar puede ser mas o menos tiempo), calcular un hash tipo SHA-512 para el mismo fichero puede suponer 5 días, lo que a día de hoy es un tiempo desproporcionado y más si no es un solo fichero, si no que son cientos de discos duros de ese tamaño. Sería como pedir que la bolsa en la que se guarda una evidencia  se lacre con un sello untado en ¡sangre de unicornio! Seguro que ese sello sería mucho más difícil de manipular, pero no creo que sea muy eficiente hacerlo así, además, al unicornio no creo que le haga mucha gracia. Ahora hablando en serio, no hay que olvidar que para declarar una prueba nula (que no ilícita o prohibida) no es suficiente con la mera sospecha de la manipulación de la prueba. Esto dicho así queda un poco aburrido, por lo que voy a utilizar un ejemplo distinto que viene a ser algo así: La colisión entre hashes de firmado digital vendría a ser como el símil de  dos personas que compartan el mismo ADN (difícil), aunque por probabilidad pueda existir esta posibilidad, no quiere decir que exista. Volviendo a los hashes criptográficos, se puede dar la circunstancia de colisión entre dos hashes, pero esto no significa que los ficheros sean congruentes entre sí, ni mucho menos con el contexto de la prueba. Siguiendo con el símil del ADN, sería como tener que añadir cinco piernas, unas alas y dos cabezas a una persona para que pudieran tener el mismo ADN que otra persona distinta. Ya sé que es un símil bizarro y poco realista, pero creo que es una forma adecuada de explicarlo. Volviendo a la temática de los hashes, no tiene sentido disponer de una imagen forense de: por ejemplo, un disco duro marca Western Sheriff de 4TB, con número de serie “taltal…” al cual se le calcula un hash X y lograr obtener una colisión de ese hash, con el hash de un simple fichero de texto. Efectivamente la colisión existe, pero a todas luces no es congruente ni compatible con el contexto de ambos ficheros. No quiero decir con esto que no existan colisiones entre ficheros del mismo tipo, de hecho a continuación os mostraré una colisión entre dos pdf distintos que arrojan el mismo hash MD5. En la primera captura, se observan dos ficheros PDF, el primero de ellos predice que el próximo presidente de Estados Unidos será: Barack Obama y el segundo, predice que será: Paris Hilton, como salta a la vista son dos ficheros completamente distintos.

Fig 12. Dos ficheros pdf distintos.

Sin embargo al calcular el hash MD5 de estos ficheros, el sistema arroja el mismo hash para ambos, lógicamente esto es una colisón del MD5.

Fig 13. Colisión de un hash MD5

 Pero ya al  calcular el hash SHA1 de ambos, se comprueba que efectivamente son distintos, al arrojar valores distintos.

Fig 14. Los mismos ficheros con SHA1 no colisionan.

Esta demo es muy visual e impactante, pero realmente no es tan sencillo lograr ese tipo de colisión. Por lo que al final se llega a una conclusión: que lo que realmente importa en todo esto es la cadena de custodia (si, eso que veíamos en: CSI Las Vegas, cuando Grissom metía una turunda con una muestra de ADN dentro de un bote bien precintado, referenciado individualmente y custodiado)

7.) Siempre hay que calcular el hash de cualquier evidencia digital:  Como en el caso anterior, la respuesta es: depende, y depende porque cada tipo de evidencia digital hay que tratarla de forma singularizada y no a granel como si fueran todas iguales. Quizás el ejemplo más claro lo podemos encontrar en discos duros sólidos SSD con el comando TRIM activado o incluso en teléfono móviles de última generación. Por ejemplo, un disco duro duro SSD, solo por el mero hecho de conectarlo a la corriente eléctrica, su controladora ejecutará de forma automática un comando llamado TRIM pensado para aumentar el rendimiento de estos discos, pero que a nivel forense implica que los bits del disco se reasignen y por lo tanto, cualquier hash que se hubiera calculado del mismo, cambiará totalmente.

Fig 15. Disco Duro SSD con el comando TRIM

¿Soluciones?, pues existen varias, desde clonar el disco duro SSD a otro disco magnético de toda la vida al cual si se le puede calcular un hash, o también se puede utilizar otra técnica totalmente innovadora y de última generación, que no es otra que meter el disco duro SSD dentro de una bolsa debidamente precintada y referenciada. Es decir,  lo que viene a ser una Cadena de Custodia tradicional de toda la vida, la misma que se utiliza para resguardar un cuchillo con restos de sangre de un asesinato o la vaina del cartucho de una pistola utilizada. A veces nos empeñamos en que tiene que ser todo “ciber” o “digital” con sus hashes, firmas, claves privadas… cuando existen métodos tradicionales totalmente validos, mucho más rápidos y muy efectivos para mantener y garantizar una debida cadena de custodia, que se considere valida en cualquier procedimiento judicial. Es decir, la cadena de custodia “ciber” o “digital” es un elemento adicional a la garantía de la prueba, ya que en todo caso, siempre existirá una cadena de custodia tradicional, que en procedimientos penales estará supervisada por la propia Autoridad Judicial.

Así que recuerda: Si tienes un fichero al que se le ha calculado un hash, lo puedes cortar, copiar y pegar, incluso cambiarle el nombre (aunque a lo mejor no deberías) que el hash no cambiará, pero si decides abrirlo, en función del fichero que sea, lo puedes alterar de forma irreparable.

¡Ah! Se me olvidaba: como dije en la receta inicial, un hash MD5, SHA1… siempre está formado por valores hexadecimales: solo pueden ser números del 0 al 9 y letras de la A a la F, por lo que es imposible que una hash contenga una Z, una J o una M… Si a alguien se le ocurre en un procedimiento judicial tratar de anular una prueba tratando de crear una duda razonable al no poder distinguir a simple vista si en un hash, el valor que está escrito es el número cero (0) o la letra ó (O), que antes de hacerlo, lea este articulo. 😉

Salu2

Manuel Guerra

Manuel Guerra

Mi nombre es Manuel Guerra. Investigador especializado en: [eCrime] | [Forensic] && [Hacking].

Editor de GLIDER.es

Navegación de la entrada


Comentarios

  • Ildefonso

    Buen artículo Manuel.

    Yo añadiría para complementar la posibilidad de utilizar programas de adqusición de imagenes forenses, tipo FTK para abrir esos documentos que mencionas de la clase “office” , donde una vez protegido contra escritura no tendríamos problema respecto al HASH.

    Igualmente un fichero .doc si no es excesivamente pesado, abriendolo con el bloc de notas, creo que evitariamos esa modoficación automática.

    • Manuel Guerra

      Manuel Guerra

      Hola Ildefonso, tengo en mente hacer otro articulo sobre el tratamiento de esas evidencias digitales 😉

      • Ildefonso

        Estaré esperándolo. 👏👏👏

  • José Mejuto

    Hola,

    Dos pequeñas cosas, una, al principio del artículo (felicidades por cierto) hablas de hash y 512 bits, dando a entender que un hash tiene 512 bits siempre ( ya se que sabes que no 🙂 ).

    La segunda es un poco más rebuscada:

    ¡Ah! Se me olvidaba: como dije en la receta inicial, un hash MD5, SHA1… siempre está formado por valores hexadecimales: solo pueden ser números del 0 al 9 y letras de la A a la F […]

    Un hash es un número de “n” bits al que se le pueden dar diferentes representaciones aunque por convención la habitual es hexadecimal. Nada impide que un hash se represente en Base64 o cualquier otro formato, aunque desde luego hexadecimal, si va a ser manejado por humanos, es lo mejor al evitar ciertas ambigüedades como bien dices.

    Yo siempre recomiendo expresar los hashes como (ejemplo):

    Hash “Algoritmo”-“Bits” (Hexadecimal) : 123456789012345678901234567890AB

    Gracias de nuevo por el artículo. Como me gusta la informática forense 🙂

    PD: Un botón de vista previa de los comentarios vendría muy bien.

    • Manuel Guerra

      Manuel Guerra

      Hola José, efectivamente, sobre esos dos detalles que comentas tienes razón, básicamente hablo de la forma a la que mas acostumbrados estamos de ver un hash,que es la representación de un hash sha1, md5… en hexadecimal 😉

      Gracias por el comentario.

      Toma nota lo de la vista previa de los comentarios.

      Salu2

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puede usar las siguientes etiquetas y atributos HTML:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>