Introducción
John the Ripper (JtR) es una popular y potente herramienta de auditoría de seguridad de contraseñas y recuperación de contraseñas de código abierto. Puede realizar el descifrado de contraseñas utilizando varios modos, como el modo "single crack", el modo "wordlist" y el modo "incremental".
Más allá de estos modos estándar, JtR ofrece un "Modo Externo" increíblemente flexible. Este modo le permite utilizar un programa o script externo para generar candidatos a contraseñas. Esto le otorga un control total sobre la lógica de generación de contraseñas, permitiéndole crear patrones de contraseñas altamente personalizados y complejos que no son posibles con otros modos.
En este laboratorio, aprenderá los fundamentos del Modo Externo de JtR. Comenzará comprendiendo los conceptos básicos, luego escribirá, compilará y utilizará su propio programa C personalizado para generar contraseñas. También aprenderá técnicas básicas de depuración y aplicará sus conocimientos a un escenario más práctico.
Comprender los conceptos básicos del Modo Externo
En este paso, aprenderá los conceptos fundamentales del Modo Externo de John the Ripper. Este modo funciona ejecutando un programa externo que usted define. John the Ripper lee la salida estándar de este programa, tratando cada línea como un candidato a contraseña potencial.
Estos modos externos se definen en el archivo de configuración john.conf, que normalmente se encuentra en /etc/john/john.conf. Cada modo externo se define dentro de una sección como [List.External:NombreModo].
Examinemos una definición de modo externo existente en el archivo de configuración predeterminado para ver cómo está estructurada. Buscaremos el modo Keyboard (Teclado), que simula candidatos a contraseñas basados en patrones de recorrido del teclado.
Ejecute el siguiente comando para ver la configuración del modo Keyboard:
grep -A 10 "\[List.External:Keyboard\]" /etc/john/john.conf
Verá un bloque de código similar a C. La función más importante es generate(), que es responsable de producir los candidatos a contraseñas.
Para ver un modo externo en acción, puede ejecutar john con la opción --stdout. Esto le indica a John que imprima los candidatos generados en la pantalla en lugar de intentar descifrar un hash. Probemos el modo Keyboard.
john --stdout --external=Keyboard | head -n 5
Este comando selecciona el modo externo Keyboard y canaliza su salida a head, que le muestra los primeros 5 candidatos a contraseñas generados. La salida será una secuencia de caracteres que representan patrones del teclado.
q
w
e
r
t
Esto demuestra el principio básico: John the Ripper ejecuta la lógica definida en el modo externo y utiliza su salida como fuente de contraseñas. En los siguientes pasos, crearemos nuestro propio programa para que actúe como fuente.
Escribir un script simple de Modo Externo
En este paso, escribirá y compilará su primer script simple de modo externo utilizando el lenguaje de programación C. Nuestro objetivo es crear un programa que genere una lista fija de contraseñas y luego configurar John the Ripper para que lo utilice.
Primero, creemos un archivo fuente de C llamado simple_gen.c usando el editor nano.
nano simple_gen.c
Ahora, copie y pegue el siguiente código C en el editor nano. Este programa simplemente imprimirá tres contraseñas diferentes en la salida estándar, cada una en una nueva línea.
#include <stdio.h>
int main() {
printf("pass1\n");
printf("pass2\n");
printf("pass3\n");
return 0;
}
Presione Ctrl+X, luego Y, y Enter para guardar el archivo y salir de nano.
A continuación, compile este código C en un archivo ejecutable llamado simple_gen utilizando el compilador gcc.
gcc -o simple_gen simple_gen.c
Ahora que tenemos nuestro ejecutable, necesitamos indicarle a John the Ripper cómo usarlo. Haremos esto creando una copia local del archivo de configuración en nuestro directorio de proyecto y agregando una nueva definición de modo externo.
cp /etc/john/john.conf ./my_john.conf
Abra el nuevo archivo my_john.conf con nano.
nano my_john.conf
Desplácese hasta el final del archivo y agregue el siguiente bloque de configuración. Esto define un nuevo modo externo llamado MySimple que ejecuta nuestro programa simple_gen.
[List.External:MySimple]
void generate()
{
exec("./simple_gen");
}
Guarde y salga de nano (Ctrl+X, Y, Enter).
Finalmente, probemos nuestro nuevo modo externo. Usaremos la opción --stdout nuevamente para ver la salida, y la opción --config para indicar a John que use nuestro archivo de configuración personalizado.
john --stdout --external=MySimple --config=./my_john.conf
Debería ver la salida exacta de nuestro programa C, lo que confirma que John the Ripper está ejecutando correctamente nuestro script personalizado.
pass1
pass2
pass3
Implementar lógica de generación de contraseñas personalizada
En este paso, mejorará su script para implementar una lógica de generación de contraseñas más dinámica. En lugar de una lista fija, generaremos contraseñas basadas en un patrón: una palabra base seguida de una secuencia de números. Este es un patrón común para contraseñas débiles.
Modifiquemos nuestro programa C para generar contraseñas como labex0, labex1, labex2, y así sucesivamente.
Abra el archivo simple_gen.c nuevamente con nano.
nano simple_gen.c
Reemplace el código existente con el siguiente. Esta nueva versión utiliza un bucle for para agregar números del 0 al 199 a la palabra base "labex".
#include <stdio.h>
int main() {
char *base_word = "labex";
for (int i = 0; i < 200; i++) {
printf("%s%d\n", base_word, i);
}
return 0;
}
Guarde y salga de nano. Ahora, vuelva a compilar el programa con gcc para aplicar los cambios.
gcc -o simple_gen simple_gen.c
Probemos el generador actualizado con la opción --stdout para ver una muestra de la nueva salida.
john --stdout --external=MySimple --config=./my_john.conf | head -n 5
La salida ahora debería mostrar el nuevo patrón.
labex0
labex1
labex2
labex3
labex4
Ahora, la prueba real. Utilizaremos nuestro modo externo personalizado para descifrar el hash de contraseña que preparamos durante la configuración. La contraseña para testuser es labex123. Nuestro script genera este candidato, por lo que debería encontrar una coincidencia.
Ejecute el siguiente comando para iniciar el proceso de descifrado. Tenga en cuenta que hemos eliminado --stdout y agregado la ruta a nuestro archivo de hashes, hashes.txt.
john --external=MySimple --config=./my_john.conf ./hashes.txt
John ejecutará su script, generará candidatos y los probará contra el hash. Debería encontrar la contraseña rápidamente. La salida se verá algo así:
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
labex123 (testuser)
1g 0:00:00:00 DONE (2024-05-20 08:30) 100.0g/s 12300p/s 12300c/s 12300C/s labex123..labex130
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Para confirmar la contraseña descifrada, use la opción --show.
john --show ./hashes.txt
Esto mostrará la contraseña descifrada junto al nombre de usuario.
testuser:labex123:1001:1001::/home/testuser:/bin/sh
1 password hash cracked, 0 left
Depurar scripts de Modo Externo
En este paso, aprenderá algunas técnicas básicas para depurar sus scripts de modo externo. Cuando un script no funciona como se espera, puede ser complicado diagnosticarlo porque está siendo ejecutado por otro programa (John the Ripper).
Un método de depuración común y efectivo es escribir mensajes de registro desde su script a un archivo separado. Esto le permite rastrear su flujo de ejecución e inspeccionar los valores de las variables.
Modifiquemos nuestro programa C para escribir en un archivo de registro llamado debug.log. Abra simple_gen.c con nano.
nano simple_gen.c
Reemplace el código con la siguiente versión. Este código abre debug.log para escritura y luego usa fprintf para escribir mensajes de estado en él durante la ejecución.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *log_file = fopen("debug.log", "w");
if (log_file == NULL) {
// Cannot open log file, exit
return 1;
}
fprintf(log_file, "Debug: Script started.\n");
char *base_word = "labex";
for (int i = 0; i < 200; i++) {
printf("%s%d\n", base_word, i);
fprintf(log_file, "Debug: Generated candidate %s%d\n", base_word, i);
}
fprintf(log_file, "Debug: Script finished.\n");
fclose(log_file);
return 0;
}
Guarde y salga de nano, luego vuelva a compilar el programa.
gcc -o simple_gen simple_gen.c
Ahora, ejecute John the Ripper nuevamente. No necesitamos ver los candidatos a contraseña, por lo que podemos redirigir la salida estándar a /dev/null. La parte importante es que nuestro script se ejecutará y creará el archivo de registro.
john --stdout --external=MySimple --config=./my_john.conf > /dev/null
El comando se ejecutará por un momento y finalizará. Ahora, debería existir un archivo debug.log en su directorio de proyecto. Veamos su contenido.
cat debug.log | head -n 5
Debería ver los mensajes de depuración que agregamos a nuestro programa.
Debug: Script started.
Debug: Generated candidate labex0
Debug: Generated candidate labex1
Debug: Generated candidate labex2
Debug: Generated candidate labex3
Esta técnica es invaluable para encontrar problemas en su lógica, como bucles incorrectos, valores de variables erróneos o errores de acceso a archivos, sin la interferencia de la propia salida de John the Ripper.
Aplicar Modo Externo a Escenarios Específicos
En este paso, aplicará sus conocimientos a un escenario más práctico. En lugar de usar una palabra base codificada, su script leerá una lista de palabras base de un archivo y generará variaciones para cada una. Este es un enfoque mucho más potente y realista.
Primero, creemos un archivo simple de lista de palabras llamado words.txt que contenga algunas palabras base potenciales.
echo "admin" > words.txt
echo "user" >> words.txt
echo "guest" >> words.txt
A continuación, modificaremos nuestro programa C para leer este archivo. El programa necesitará aceptar el nombre del archivo de la lista de palabras como argumento de línea de comandos. Abra simple_gen.c con nano.
nano simple_gen.c
Reemplace el código con el siguiente. Esta versión lee un nombre de archivo de la línea de comandos, abre ese archivo y, por cada palabra que lee, genera tres candidatos a contraseña: la palabra en sí, la palabra seguida de "123" y la palabra seguida de "2024".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <wordlist_file>\n", argv[0]);
return 1;
}
FILE *file = fopen(argv[1], "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
char line[256];
while (fgets(line, sizeof(line), file)) {
// Remove newline character from the end of the line
line[strcspn(line, "\n")] = 0;
// Generate variations for the word
printf("%s\n", line);
printf("%s123\n", line);
printf("%s2024\n", line);
}
fclose(file);
return 0;
}
Guarde, salga y vuelva a compilar el programa.
gcc -o simple_gen simple_gen.c
Ahora, debemos actualizar nuestro archivo my_john.conf para pasar el nombre del archivo words.txt como argumento a nuestro script. Creemos un nuevo modo externo llamado MyAdvanced para esto. Abra my_john.conf con nano.
nano my_john.conf
Desplácese hasta el final del archivo y agregue esta nueva sección. Observe cómo "words.txt" se pasa como segundo parámetro a la función exec.
[List.External:MyAdvanced]
void generate()
{
exec("./simple_gen", "words.txt");
}
Guarde y salga de nano. Finalmente, pruebe su nuevo modo externo avanzado.
john --stdout --external=MyAdvanced --config=./my_john.conf
La salida ahora debería ser una lista de candidatos a contraseña generados a partir de las palabras en su archivo words.txt, con las variaciones especificadas aplicadas a cada una.
admin
admin123
admin2024
user
user123
user2024
guest
guest123
guest2024
Ha creado con éxito un generador de contraseñas flexible y basado en archivos para John the Ripper.
Resumen
¡Felicitaciones por completar este laboratorio! Ha explorado con éxito el potente Modo Externo de John the Ripper.
En este laboratorio, ha aprendido:
- El concepto básico del Modo Externo de John the Ripper y cómo utiliza programas externos para generar candidatos a contraseñas.
- Cómo escribir, compilar y utilizar un programa C simple como generador de contraseñas.
- Cómo configurar un modo externo personalizado en el archivo
john.conf. - Cómo implementar lógica de generación de contraseñas dinámica basada en patrones.
- Cómo utilizar su modo personalizado para descifrar con éxito un hash de contraseña.
- Una técnica básica pero efectiva para depurar sus scripts externos registrando en un archivo.
- Cómo crear un script más avanzado y práctico que lee palabras base de un archivo.
Las habilidades que ha adquirido proporcionan una base para crear reglas de descifrado de contraseñas altamente especializadas y adaptadas a objetivos y escenarios específicos. Puede explorar más este tema utilizando otros lenguajes de scripting como Python o Perl, o implementando una lógica de mutación y generación de contraseñas aún más compleja.


