Imagen conceptual sobre cómo descifrar un hash de contraseña, con un fondo digital de códigos y términos de ciberseguridad.
Aprende las técnicas y herramientas más efectivas para descifrar un hash de contraseña y comprende cómo funcionan estos ataques.

Recuperar una Contraseña a partir de su Hash: Guía Práctica

Imagina que te encuentras con una base de datos que contiene una serie de contraseñas, pero en forma de cadenas de texto incomprensibles, como esta:

5f4dcc3b5aa765d61d8327deb882cf99

A primera vista, no parece nada legible. Sin embargo, este hash de contraseña corresponde a algo muy familiar: la palabra “password“.

En este tutorial, descubrirás cómo entender, generar e intentar descifrar un hash de contraseña, tal como lo haría un hacker ético o un experto en ciberseguridad.

Diagrama que explica el hash de una contraseña.
El hashing transforma un texto legible en una cadena alfanumérica única y de longitud fija.

Este tipo de ejercicio se denomina “desafío de cracking de hash” y se propone con frecuencia en formaciones de seguridad informática o en competiciones conocidas como CTF (Capture The Flag).

Pero antes de sumergirte en la parte práctica, es fundamental comprender qué es un hash, para qué sirve y por qué está diseñado para ser… irreversible.

¿Qué es un Hash y Cómo Funciona?

Una función de hashing es un algoritmo matemático que transforma un dato (como una contraseña, un archivo o un texto) en una cadena de caracteres única y de longitud fija.

Este proceso se llama hashing, y el resultado se denomina huella o digest.

Tomemos un ejemplo simple con la función MD5. En PHP, puedes generar un hash MD5 de la siguiente manera:

<?php
$contrasena = "hola";
$hash = md5($contrasena);
echo $hash;

El resultado mostrado será:

4d186321c1a7f0f354b297e8914ab240

Si pruebas con otra palabra, incluso muy similar (por ejemplo, “hola1”), el hash será completamente diferente. Este comportamiento se conoce como el efecto avalancha: una modificación mínima en el texto original provoca una transformación total del resultado.

Las funciones de hashing más conocidas son:

  • MD5 (antigua, muy rápida pero hoy considerada vulnerable)
  • SHA-1 (también obsoleta)
  • SHA-256, SHA-512 (más seguras)
  • bcrypt, argon2, scrypt (diseñadas específicamente para el hashing de contraseñas)

El propósito de un hash es garantizar la seguridad: cuando un usuario inicia sesión, el sitio no almacena su contraseña en texto plano, sino únicamente su hash. Cuando introduce su contraseña, el sitio la vuelve a hashear y compara el resultado con el que está en la base de datos.

Para profundizar en el tema del hashing de contraseñas.

La Irreversibilidad Teórica de un Hash de Contraseña

El hashing no es un cifrado. El cifrado (como AES o RSA) permite descifrar un mensaje si se tiene la clave. El hashing, en cambio, es unidireccional: no existe una “clave de descifrado”.

Por esta razón, es técnicamente incorrecto hablar de ‘desencriptar una contraseña hash’, ya que no existe un proceso de descifrado. El objetivo es encontrar el texto original que produce el mismo hash.

En otras palabras, no hay un botón de “invertir el hash”. Pero… entonces, ¿por qué este tutorial habla de “recuperar una contraseña a partir de un hash“?

Porque, en la práctica, los humanos no siempre eligen contraseñas robustas. Y como el hashing es determinista (la misma palabra siempre produce el mismo hash), es posible utilizar bases de datos de hashes conocidos para adivinar el original.

Por ejemplo:

md5("password") = 5f4dcc3b5aa765d61d8327deb882cf99

Este hash ha sido calculado millones de veces y figura en todas las bases de datos públicas de hashes. Si te lo encuentras, no necesitas “romperlo”: basta con buscarlo.

Esto es lo que se conoce como un ataque por diccionario o una búsqueda en una base de datos precalculada.

Métodos para Descifrar una Contraseña Hash

Los atacantes (o investigadores de seguridad) utilizan tres métodos principales para intentar recuperar una contraseña hash a partir de su huella digital:

Respuesta Rápida: ¿Cómo recuperar una contraseña a partir de un hash?

  1. Búsqueda en bases de datos: Utiliza servicios online como CrackStation que tienen millones de hashes precalculados.
  2. Ataque por diccionario: Prueba una lista de contraseñas comunes (ej. rockyou.txt), hashea cada una y compara el resultado.
  3. Ataque por fuerza bruta: Genera y prueba todas las combinaciones de caracteres posibles hasta encontrar una coincidencia.
  1. La búsqueda en una base de datos de hashes conocida
    Para buscar un hash de contraseña online, sitios como CrackStation.net o Hashes.com contienen millones de hashes precalculados. Solo tienes que introducir tu hash y esperar una coincidencia.
  2. El ataque por diccionario
    Se prueba un gran número de palabras de un diccionario (por ejemplo, las 10 000 contraseñas más utilizadas). Cada palabra se hashea y se compara con el hash a recuperar.
  3. El ataque por fuerza bruta (brute force)
    Se prueban todas las combinaciones posibles de caracteres hasta encontrar la correcta. Este método garantiza un resultado, pero puede ser extremadamente lento dependiendo de la longitud de la contraseña y del algoritmo de hashing utilizado.

Veamos ahora cómo puedes simular estas técnicas por ti mismo, de forma totalmente legal y con fines educativos.

Para descubrir cómo se prueba o crackea una contraseña.

Desafío Práctico: Scripts para Romper un Hash

Resultado de un script para descifrar un hash de contraseña.
El script compara el hash de cada palabra del diccionario hasta encontrar la coincidencia.

Para este ejercicio, imagina que has obtenido este hash:

5f4dcc3b5aa765d61d8327deb882cf99

Tu misión: encontrar la contraseña original utilizando un pequeño script en PHP.

Paso 1: Crea tu archivo crack.php

<?php
$hash_a_encontrar = "5f4dcc3b5aa765d61d8327deb882cf99";
$diccionario = ["123456", "admin", "password", "hola", "qwerty", "contraseña"];

foreach ($diccionario as $palabra) {
    if (md5($palabra) === $hash_a_encontrar) {
        echo "Contraseña encontrada: $palabra";
        exit;
    }
}
echo "No se encontró ninguna contraseña.";

Cuando ejecutas este código, el script prueba cada palabra del diccionario, la hashea con MD5 y la compara con el hash que intentas romper.

El resultado:

Contraseña encontrada: password

¡Felicidades, acabas de “crackear” un hash!

Paso 2: ¿Y si la contraseña no estuviera en el diccionario?

En ese caso, hay que pasar a otro enfoque: la fuerza bruta. Aquí te recomendamos nuestro tutorial de ataque por fuerza bruta con IA.

Aquí tienes un ejemplo simple en PHP que genera todas las combinaciones de letras minúsculas de 4 caracteres:

<?php
$hash_a_encontrar = "81dc9bdb52d04dc20036dbd8313ed055"; // 1234

$letras = range('a', 'z');
$numeros = range('0', '9');
$caracteres = array_merge($letras, $numeros);

function fuerzaBruta($hash, $caracteres, $palabra = '') {
    if (md5($palabra) === $hash) {
        echo "Contraseña encontrada: $palabra";
        exit;
    }
    if (strlen($palabra) < 4) {
        foreach ($caracteres as $c) {
            fuerzaBruta($hash, $caracteres, $palabra . $c);
        }
    }
}

fuerzaBruta($hash_a_encontrar, $caracteres);

Este script prueba todas las combinaciones de 1 a 4 caracteres compuestas de letras y números. Incluso para una longitud tan corta, el número de posibilidades ya es muy elevado (36^4 = 1,679,616).

Es por esta razón que las contraseñas largas y complejas son muy difíciles de romper.

Paso 3: Mismo concepto en Python

Python se utiliza a menudo para este tipo de pruebas porque su ejecución es más rápida que la de PHP. Aquí tienes un ejemplo equivalente:

import hashlib
from itertools import product
import string

hash_a_encontrar = "5f4dcc3b5aa765d61d8327deb882cf99"

for longitud in range(1, 9): # Ajustado para encontrar 'password'
    for palabra_tupla in product(string.ascii_lowercase, repeat=longitud):
        palabra = ''.join(palabra_tupla)
        if hashlib.md5(palabra.encode()).hexdigest() == hash_a_encontrar:
            print("Contraseña encontrada:", palabra)
            exit()

Aquí, utilizamos itertools.product para generar todas las combinaciones posibles. El código puede tardar varios minutos en ejecutarse, pero ilustra perfectamente la lógica.

Herramientas Profesionales y Defensas contra el Cracking

Ahora abordaremos conceptos más avanzados y concretos. En una futura guía, profundizaremos en qué son las rainbow tables, cómo funcionan herramientas profesionales como Hashcat y John the Ripper, y, sobre todo, cuáles son las buenas prácticas para proteger a tus usuarios y evitar que sus contraseñas sean recuperadas a partir de un hash.

Ponte a Prueba: Desafíos de Cracking (CTF)

Para poner en práctica lo que acabas de aprender, aquí tienes un pequeño ejercicio que puedes realizar en casa, en un entorno controlado. Puedes enviarnos las respuestas por X (Twitter): @esgeeks.

Este ejercicio propone tres niveles de dificultad e incluye pistas para guiarte. Recuerda que estos ejercicios son únicamente para fines de aprendizaje: nunca intentes romper contraseñas en sistemas o cuentas que no te pertenecen.

Ejercicio 1 — nivel fácil (MD5)

Aquí tienes un hash MD5 a recuperar. Es un caso simple y deliberadamente trivial para empezar:

d8578edf8458ce06fbc5bb76a58c5ca4

Pista: esta contraseña es muy común y se compone de un patrón de teclado común seguido de tres números.

Ejercicio 2 — nivel intermedio (SHA-1)

Aquí tienes un hash SHA-1 a recuperar:

9377B04735E287DA00B4F8053EA029A2C2CD3C29

Pista: la contraseña es corta y contiene letras y números. Fue elegida para probar una búsqueda por diccionario extendida o un ataque de fuerza bruta controlado.

Ejercicio 3 — nivel avanzado (SHA-256 con salt proporcionado)

Para este tercer desafío, añadimos un salt. El salt es: SALT2026
El hash SHA-256 (calculado sobre la concatenación salt + contraseña) es:

eceb8d2ee098706d0d04f0e8b99db953fd5c381757de6d6c6a62c393b171efae

Pista: la contraseña es una palabra simple en inglés-español (entendible por igual en ambos idiomas) y en minúsculas. Como se proporciona el salt, puedes usarlo directamente en tus scripts para reconstruir y probar los candidatos.

Ejemplos de scripts optimizados para empezar (a ejecutar localmente)

Ejemplo en PHP: ataque por diccionario optimizado (usa un archivo diccionario.txt con candidatos, uno por línea)

<?php
$hash_md5 = "d8578edf8458ce06fbc5bb76a58c5ca4";
$hash_sha1 = "9377B04735E287DA00B4F8053EA029A2C2CD3C29";
$salt = "SALT2025";
$hash_salted_sha256 = "eceb8d2ee098706d0d04f0e8b99db953fd5c381757de6d6c6a62c393b171efae";

$dico = fopen("diccionario.txt", "r");
if (!$dico) { die("Imposible abrir diccionario.txt\n"); }

$md5_encontrado = false;
$sha1_encontrado = false;
$salted_sha256_encontrado = false;

while (($linea = fgets($dico)) !== false) {
    $palabra = trim($linea);

    if (!$md5_encontrado && md5($palabra) === $hash_md5) {
        echo "Ej1 encontrado (MD5): $palabra\n";
        $md5_encontrado = true;
    }
    if (!$sha1_encontrado && sha1($palabra) === $hash_sha1) {
        echo "Ej2 encontrado (SHA1): $palabra\n";
        $sha1_encontrado = true;
    }
    if (!$salted_sha256_encontrado && hash('sha256', $salt . $palabra) === $hash_salted_sha256) {
        echo "Ej3 encontrado (salted SHA256): $palabra\n";
        $salted_sha256_encontrado = true;
    }

    // Salir del bucle si ya se encontraron todos los hashes
    if ($md5_encontrado && $sha1_encontrado && $salted_sha256_encontrado) {
        echo "Todos los hashes resueltos.\n";
        break;
    }
}
fclose($dico);

Ejemplo en Python: generación por fuerza bruta optimizada

import hashlib
from itertools import product
import string

hash_md5 = "d8578edf8458ce06fbc5bb76a58c5ca4"
hash_sha1 = "9377B04735E287DA00B4F8053EA029A2C2CD3C29"
salt = "SALT2025"
hash_salted_sha256 = "eceb8d2ee098706d0d04f0e8b99db953fd5c381757de6d6c6a62c393b171efae"

md5_found = False
sha1_found = False
salted_found = False

alfabeto = string.ascii_lowercase + string.digits

print("Iniciando búsqueda por fuerza bruta...")
for length in range(1, 9): # Búsqueda hasta 8 caracteres
    if md5_found and sha1_found and salted_found:
        break
    print(f"Probando contraseñas de longitud {length}...")
    for tup in product(alfabeto, repeat=length):
        candidato = ''.join(tup)

        if not md5_found and hashlib.md5(candidato.encode()).hexdigest() == hash_md5:
            print("Ej1 encontrado (MD5):", candidato)
            md5_found = True

        if not sha1_found and hashlib.sha1(candidato.encode()).hexdigest() == hash_sha1:
            print("Ej2 encontrado (SHA1):", candidato)
            sha1_found = True

        if not salted_found and hashlib.sha256((salt + candidato).encode()).hexdigest() == hash_salted_sha256:
            print("Ej3 encontrado (salted SHA256):", candidato)
            salted_found = True

        if md5_found and sha1_found and salted_found:
            print("Todos los hashes resueltos.")
            exit() # Salir del script completamente

print("Búsqueda finalizada.")

Consejos prácticos para abordar el ejercicio:

  • Comienza con un ataque por diccionario usando listas de palabras comunes (rockyou.txt o diccionarios más pequeños para empezar).
  • Si no obtienes resultados, aplica reglas simples (añadir números, sustituciones clásicas) o reduce el campo de búsqueda para la fuerza bruta, apuntando primero a longitudes cortas.
  • Para el ejercicio 3, no olvides añadir el salt exactamente en el orden correcto (en este caso, salt + contraseña).
  • Vigila el tiempo de ejecución y prueba con palabras cortas antes de ampliar la búsqueda.

Envía tus respuestas por X (Twitter)

Cuando hayas encontrado las palabras correspondientes, envíalas por X en un mensaje público o DM a la cuenta @esgeeks. Si prefieres una revisión privada para verificar tus resultados antes de publicarlos, especifícalo en tu mensaje.

Recordatorio ético y legal.
Estos ejercicios tienen como objetivo el aprendizaje y la concienciación sobre la seguridad. Nunca utilices estas técnicas en sistemas para los que no tengas permiso explícito. Practica únicamente en tus propios archivos o en entornos dedicados.

¡Diviértete con este pequeño desafío!

🤞 ¡El Gran Hermano te vigila, pero sabemos cómo detenerlo!

¡No enviamos spam! Lee nuestra Política de Privacidad para más información.

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Mi Carro Close (×)

Tu carrito está vacío
Ver tienda