:::: MENU ::::

Cómo crear una Base de Datos de Hashes

¡Muy buenas amantes de la informática!
Bueno, la verdad es que ya hace siglos hice un generador de Hashes que generaba hashes en MD5 siguiendo un orden específico, el orden en cuestión era como el Excel (A, B… AZ, BA… ZZ, AAA..) pero incluyendo números y caracteres que se ponen comunmente en las contraseñas: ªº\|!@”#~$%&/()=’?

Ese generador iba metiendo todas las contraseñas en una base de datos con su respectivo hash MD5, de forma que si buscaba el hash en cuestión en la base de datos me lo devolvía desencriptado (por decirlo de alguna forma, puesto que realmente no se puede hacer eso, pero si conseguir una coincidencia a fuerza bruta, que además son infinitamente múltiples en todos los casos posibles).

El código es sencillo y os lo dejo a todos para que lo aprovechéis. En un principio hice una versión para MySQL y luego una versión Flat File. Ambos son de uso recomendado en SSDs o dispositivos de almacenamiento flash por que en discos duros es muuuuy lento y tedioso.

Código Flat File (Pastebin para mejor formato)

$c = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ªº\\|!@”#~$%&/()=\’?’;
$k = strlen($c);
function c($n)
{
global $k, $c;
$s = ”;
$r = 1;
$b = $n;
while($b > pow($k, $r))
$b -= pow($k, $r++);
for($i = 0; $r > $i; $i++)
$s = substr($c, ($n/pow($k,$i)-1)%$k, 1) . $s;
return $s;
}

$x = scandir(‘C:\\txt’);
if($x[count($x)-1] == ‘..’)
$i = 0;
else
$i = count($x)-2;
echo number_format($i, 0, ‘.’, ‘.’);
while(true)
{
$i++;
$m = c($i);
$alg = hash_algos();
$sb = ”;
$sa = ”;
foreach(hash_algos() as $b => $al)
$sa .= hash($al, $m) . ((count(hash_algos()) > ($b + 1)) ? ‘ ‘ : ”);
file_put_contents(‘C:\\txt\\’ . $i, $m . ‘ ‘ . $sa);
if($i%1000 == 0)
echo “\n” . number_format($i, 0, ‘.’, ‘.’);
}

Código para MySQL (Pastebin para mejor formato)

$x = mysqli_connect(‘127.0.0.1’, ‘root’, ‘contraseña’, ‘db’);
$c = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ªº\\|!@”#~$%&/()=\’?’;
$k = strlen($c);
function c($n)
{
global $k, $c;
$s = ”;
$r = 1;
$b = $n;
while($b > pow($k, $r))
$b -= pow($k, $r++);
for($i = 0; $r > $i; $i++)
$s = substr($c, ($n/pow($k,$i)-1)%$k, 1) . $s;
return $s;
}
$q = mysqli_query($x, ‘SELECT id FROM hashes ORDER BY id DESC LIMIT 1’);
if(mysqli_num_rows($q) == 0)
$i = 0;
else
{
$p = mysqli_fetch_assoc($q);
$i = $p[‘id’];
}
echo number_format($i, 0, ‘.’, ‘.’);
while(true)
{
$i++;
$m = c($i);
$alg = hash_algos();
$sb = ”;
$sa = ”;
foreach(hash_algos() as $b => $al)
{
$sb .= ‘, `’ . $al . ‘`’;
$sa .= ‘\” . hash($al, $m) . ((count(hash_algos()) > ($b + 1)) ? ‘\’,’ : ‘\”);
}
mysqli_query($x, ‘INSERT INTO hashes (`value`’ . $sb . ‘) VALUES (\” . mysqli_real_escape_string($x, $m) . ‘\’, ‘ . $sa . ‘)’);
if($i%100 == 0)
echo “\n” . number_format($i, 0, ‘.’, ‘.’);
}

El SQL que debéis hacer para crear la tabla es tan fácil como ejecutar un script con un foreach en el cual por cada valor de hash_algos() (función que viene en PHP para obtener un array que nos indica todos los tipos de hashes disponibles) cree una fila varchar 255 y listo. En cualquier caso, aquí lo tenéis:

CREATE TABLE IF NOT EXISTS `hashes` (
`id` int(11) NOT NULL,
`value` varchar(255) NOT NULL,
`md2` varchar(255) NOT NULL,
`md4` varchar(255) NOT NULL,
`md5` varchar(255) NOT NULL,
`sha1` varchar(255) NOT NULL,
`sha224` varchar(255) NOT NULL,
`sha256` varchar(255) NOT NULL,
`sha384` varchar(255) NOT NULL,
`sha512` varchar(255) NOT NULL,
`ripemd128` varchar(255) NOT NULL,
`ripemd160` varchar(255) NOT NULL,
`ripemd256` varchar(255) NOT NULL,
`ripemd320` varchar(255) NOT NULL,
`whirlpool` varchar(255) NOT NULL,
`tiger128,3` varchar(255) NOT NULL,
`tiger160,3` varchar(255) NOT NULL,
`tiger192,3` varchar(255) NOT NULL,
`tiger128,4` varchar(255) NOT NULL,
`tiger160,4` varchar(255) NOT NULL,
`tiger192,4` varchar(255) NOT NULL,
`snefru` varchar(255) NOT NULL,
`snefru256` varchar(255) NOT NULL,
`gost` varchar(255) NOT NULL,
`gost-crypto` varchar(255) NOT NULL,
`adler32` varchar(255) NOT NULL,
`crc32` varchar(255) NOT NULL,
`crc32b` varchar(255) NOT NULL,
`fnv132` varchar(255) NOT NULL,
`fnv1a32` varchar(255) NOT NULL,
`fnv164` varchar(255) NOT NULL,
`fnv1a64` varchar(255) NOT NULL,
`joaat` varchar(255) NOT NULL,
`haval128,3` varchar(255) NOT NULL,
`haval160,3` varchar(255) NOT NULL,
`haval192,3` varchar(255) NOT NULL,
`haval224,3` varchar(255) NOT NULL,
`haval256,3` varchar(255) NOT NULL,
`haval128,4` varchar(255) NOT NULL,
`haval160,4` varchar(255) NOT NULL,
`haval192,4` varchar(255) NOT NULL,
`haval224,4` varchar(255) NOT NULL,
`haval256,4` varchar(255) NOT NULL,
`haval128,5` varchar(255) NOT NULL,
`haval160,5` varchar(255) NOT NULL,
`haval192,5` varchar(255) NOT NULL,
`haval224,5` varchar(255) NOT NULL,
`haval256,5` varchar(255) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=486089 DEFAULT CHARSET=utf8;

ALTER TABLE `hashes`
ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `value` (`value`), ADD KEY `md2` (`md2`), ADD KEY `md4` (`md4`), ADD KEY `md5` (`md5`), ADD KEY `sha1` (`sha1`), ADD KEY `sha224` (`sha224`), ADD KEY `sha256` (`sha256`), ADD KEY `sha384` (`sha384`), ADD KEY `sha512` (`sha512`), ADD KEY `ripemd128` (`ripemd128`), ADD KEY `ripemd160` (`ripemd160`), ADD KEY `ripemd256` (`ripemd256`), ADD KEY `ripemd320` (`ripemd320`), ADD KEY `whirlpool` (`whirlpool`), ADD KEY `tiger128,3` (`tiger128,3`), ADD KEY `tiger160,3` (`tiger160,3`), ADD KEY `tiger192,3` (`tiger192,3`), ADD KEY `tiger128,4` (`tiger128,4`), ADD KEY `tiger160,4` (`tiger160,4`), ADD KEY `tiger192,4` (`tiger192,4`), ADD KEY `snefru` (`snefru`), ADD KEY `snefru256` (`snefru256`), ADD KEY `gost` (`gost`), ADD KEY `gost-crypto` (`gost-crypto`), ADD KEY `adler32` (`adler32`), ADD KEY `crc32` (`crc32`), ADD KEY `crc32b` (`crc32b`), ADD KEY `fnv132` (`fnv132`), ADD KEY `fnv1a32` (`fnv1a32`), ADD KEY `fnv164` (`fnv164`), ADD KEY `fnv1a64` (`fnv1a64`), ADD KEY `joaat` (`joaat`), ADD KEY `haval128,3` (`haval128,3`), ADD KEY `haval160,3` (`haval160,3`), ADD KEY `haval192,3` (`haval192,3`), ADD KEY `haval224,3` (`haval224,3`), ADD KEY `haval256,3` (`haval256,3`), ADD KEY `haval128,4` (`haval128,4`), ADD KEY `haval160,4` (`haval160,4`), ADD KEY `haval192,4` (`haval192,4`), ADD KEY `haval224,4` (`haval224,4`), ADD KEY `haval256,4` (`haval256,4`), ADD KEY `haval128,5` (`haval128,5`), ADD KEY `haval160,5` (`haval160,5`), ADD KEY `haval192,5` (`haval192,5`), ADD KEY `haval224,5` (`haval224,5`), ADD KEY `haval256,5` (`haval256,5`);

Espero que os sirva de ayuda para vuestros proyectos,
Saludos :B


¡Cuidado con las contraseñas!

Supongo que estaréis cansados de escuchar lo mismo cada día, cuidado con las contraseñas es una frase que os dirán muchos informáticos/hackers cuando os hablen de seguridad informática.
Por si no sabéis por que o creéis que el riesgo es inferior y os pensáis que cuando os lo decimos somos exagerados, voy a explicar varias razones por las cuales deberíais tener contraseñas largas, raras, diferentes en todos los sitios y además, a ser posible, con un segundo o incluso tercer factor de autenticación (con un segundo factor es suficiente, aun que aun así, no estamos nunca del todo seguros).

Razones para que la contraseña no tenga sentido
Sinceramente, no eres el único que sabe cuando te casastes (se acordará más tu mujer) y tampoco eres el único que sabe el nombre de tu perro. Y sí, sobre esto creo que no hay más.

Razones para que las contraseñas sean largas y raras
Básicamente una de las razones fundamentales es para evitar la fuerza bruta, que consiste en probar contraseñas hasta averiguarla, obviamente eso no lo hace una persona si no un programa, y es por ello que no se cansa de probar hasta encontrarle, obviamente llegará un punto que se dará por vencido, pero eso significa meses probando, ya que con la velocidad de los proxies que iría intercambiando, buf, mejor ni pensar en esa velocidad que nos deprimimos. Obviamente, si es una contraseña que no tenga nada que ver con internet o que sea una conexión rápida, supondría mucho menos esfuerzo, pero aun así hay una cosa llamada diccionarios, por lo que si pones algo coherente será más fácil encontrarla puesto que es lo primero que buscan dichos programas. Además, si intentan “desencriptar” (y lo pongo entre comillas por que no se desencripta) van a buscar el hash (lo cual mencionaré en la siguiente razón) y cuanto más complicada sea, menos posibilidades habrá de que la haya generado el robot que va metiendo contraseñas (si no la ha introducido otra persona ya por que apretó al azar las mismas teclas/números/símbolos que tu, lo cual es extraño).

Razones para que sean diferentes en todos los sitios
Para empezar hay sitios que ni encriptan las contraseñas al almacenarlas (lo cual es ilegal según el artículo 93.3 del reglamento que desarrolla la Ley orgánica de protección de datos), y los hay que encriptan las contraseñas con métodos comunes, por ejemplo, una de las encriptaciones más realizadas es la de MD5. Muy bien, ¿cual es el problema de eso? pues muy fácil, si encuentran una vulnerabilidad en el sitio web en cuestión mediante la cual puedan acceder a la base de datos (o al sitio donde guarden dichas contraseñas) simplemente será tan fácil como buscar tu nombre para encontrarlas, y si las tienen y tienes la misma contraseña en todas las páginas webs… Creo que no hace falta decir nada más.
¿Y que pasa si está encriptada diréis algunos? Pues como he mencionado anteriormente hay webs que ofrecen gigantescas bases de datos repletas de palabras y combinaciones con un montón de variedad de Hashes para poder encontrar dicha contraseña. Es posible que otra contraseña que no sea la tuya también te permita entrar a una web puesto que hay un número de hashes limitado y por ello se van repitiendo, pero hay poquisimas posibilidades entre incontables millones, por lo que eso no debería preocuparte, pero si que es posible que si pongo ‘a’ en un caso hipotético eso coincida con ‘sijndf9uewghf98342egf4eg894g89324tg89gt80934e2’ (me lo he inventado, pero podría ocurrir), y entonces la contraseña ‘sijndf9uewghf98342egf4eg894g89324tg89gt80934e2’  pasaría a ser una de las más inseguras del mundo. Adjunto abajo un ejemplo de contraseña “desencriptada”.

Hash 'e10adc3949ba59abbe56e057f20f883e' MD5 "desencriptado"

Hash ‘e10adc3949ba59abbe56e057f20f883e’ MD5 “desencriptado”

Creo que con eso queda claro el por qué usar contraseñas diferentes en todos los sitios, contraseñas largas (si eres un gurú de la seguridad comprobando que no coincida con ninguna contraseña de al menos 8 caracteres con todos los simbolos en MD5 y SHA1), contraseñas con muchisimos símbolos y sin sentido para evitar que la descifren y evitar fuerza bruta y diccionarios, etc.

Una herramienta que os puede resultar útil es haveibeenpwned.com, una web que comprueba si has sido víctima sin darte cuenta de accesos indeseados a varias empresas, entre ellas Adobe, que tubo una gran crisis no hace demasiado tiempo, y lo comprueba ya que muchas veces las contraseñas son publicadas en lugares como pastebin (y también otro tipo de información sensible). Obviamente no contiene todas, pero si bastantes, si sales ahí, al menos date por aludido y cambia la contraseña, y no digas “no van a por mi, no me harán nada”, por que esto no es así, y si no puedes buscar libros, documentales, vídeos, charlas, etc.

Ya que estoy os cuento una anécdota:
Hará un año más o menos, me aburría bastante, así que decidí hacer un robot que generara Hashes en MD5 y SHA1 y me los guardara en una base de datos junto a su respectiva cadena de texto para poder tener contraseñas a cholón a lo MD5decoder (entre otros cientos de webs existentes que ofrecen exactamente lo mismo). El robot iba generando contraseñas con un patrón, empezaba a, b, c… y, z, aa, ab, ac… zy, zz, aaa; más o menos como Excel, pero no solo con letras, también con números y caracteres que se usan comunmente en contraseñas (es decir, los que están en el teclado), tardé solo 20 minutos y generaba hasta 10.000/segundo y los guardaba en MySQL, en nada conseguí 100 millones de contraseñas, pero lo paré por que ocupaba mucho espacio, y total, solo quería demostrar que se podía hacer, con solo 20 minutitos de mi tiempo pude hacer eso, con ello demuestro que MD5 y SHA1 no es lo mejor a la hora de encriptar. Os iba a adjuntar el código, pero cabezón de mi, lo perdí al formatear :(

Bueno, ya es martes, un día menos para llegar al fin de semana, recordad que sigo preparando un post algo especial en el cual me gustaría eneñar a crear un chat seguro en C#, y explicaros cuatro cositas sobre los chats más comunes a la par que inseguros ;)