jugando con docker

Overview

En las últimas décadas han aparecido nuevas soluciones que nos permiten afrontar los nuevos retos que se nos plantean.

Docker es un ejemplo de ello, iniciando como clon del proyecto heroku, es ahora una plataforma sobre la que desplegar infinidad de sistemas.

Es una solución de código abierto que nos permite tanto publicar servicios como de sistemas dentro de contenedores.

Mediante el aislamiento del kernel permite la ejecución independiente de los distintos * contenedores *, proporcionándonos una nueva capa de abstracción.

Con esta nueva capa de abstracción, facilita el diseño y despliegue de infraestructuras con alta disponibilidad y resiliencia.

Dispone de un amplio repositorio de imágenes, dockerhub, con diversidad de sistemas y servicios que podemos usar para el diseño de nuestra infraestructura.

Es también relevante su implicación con la seguridad, ofreciendo, en los planes profesionales, la posibilidad de escanear las vulnerabilidades de las imágenes que se suben a dockerhub. No obstante, es responsabilidad del propietario de la imagen, actualizar y mantener la imagen sin vulnerabilidades.

Solo para dejar la referencia, una herramienta muy interesante es trivy con la que también podemos analizar las vulnerabilidades de nuestras imágenes.

Docker es útil tanto para el diseño de infraestructuras seguras, para el despliegue de entornos de pruebas, preproducción, como para preparar nuestros entornos de test de intrusión, que es el punto sobre el que centraremos el post.

No es el objeto de este post ser un manual de Docker, ya disponéis de uno en la página oficial, pero sí el realizar tres pequeños ejercicios para ver su funcionamiento a nivel general y mostrar sus bondades.

Preparando un host

Como se ha comentado anteriormente, el uso de Docker, nos ofrece un nivel de abstracción que nos permite levantar servicios y sistemas, ya sea manualmente o de forma programática.

En el ejemplo a continuación, crearemos un equipo para realizar test de intrusión. Esta acción la podemos realizar tanto manualmente, instanciando un sistema base e instalando posteriormente las herramientas que necesitemos o mediante el uso de un Dockerfile, donde podemos definir una serie de acciones y crear imágenes a partir de dicha plantilla.

Para realizar los ejercicios necesitaremos la imagen del OS kali, que descargaremos a nuestro repositorio local de Docker.

1
~:$ docker pull kalilinux/kali 

Una vez realizado podemos verificar que las imágenes se han descargado correctamente con el siguiente comando:

1
2
3
4
5
~:$ docker images 

REPOSITORY TAG IMAGE ID CREATED SIZE

kalilinux/kali latest 4a681ae9009a 7 days ago 124MB

Ahora podemos instanciar el que será nuestro sistema base para empezar a trabajar con él. En este ejemplo lo estamos realizando de la imagen de kai, pero podemos usar cualquier otro sistema como base.

1
2
3
4
5
~:$ docker run -ti  kalilinux/kali  /bin/bash 

┌──(root💀c1ab1f86ad44)-[/]

└─#

Al iniciarlo con la opción “-ti” obtenemos una shell interactiva del sistema. Ahora ya podemos instalar todas las herramientas que necesitemos, realizar pruebas, etc … lo único que hay que tener en cuenta es que si detenemos la ejecución del Docker todos los cambios realizados se perderán, este no almacenará ni las nuevas aplicaciones ni los datos.

Si nos interesa guardar los cambios realizados como una nueva plantilla, lo podemos realizar del siguiente modo:

Presionar crl q o crl p para salir del contenedor sin detener su ejecución.

Podemos ejecutar el siguiente comando para verificar los contenedores activos.

1
2
3
4
5
~:$ docker ps 

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c1ab1f86ad44 kalilinux/kali "/bin/bash" 12 minutes ago Up 12 minutes pensive_almeida

Ahora podemos ejecutar el siguiente comando para crear nuestra nueva imagen. Remplazando * c1ab1f86ad44 * por el id de nuestro container.

1
~:$ docker commit c1ab1f86ad44  my/kali     

Y verificar del siguiente modo que disponemos de una nueva imagen personalizada.

1
2
3
4
5
6
7
~:$ docker images 

REPOSITORY TAG IMAGE ID CREATED SIZE

my/kali latest 49f382139b02 22 seconds ago 356MB

kalilinux/kali latest 4a681ae9009a 7 days ago 124MB

Esta opción puede ser útil para realizar pruebas, por ejemplo, de nuevas herramientas y guardar la imagen en caso de que sea de interés.

Tal y como ya hemos mencionado esta acción puede realizarse mediante definición de un fichero, en este caso crearemos un sistema para realizar los test de intrusión con nuestro set de herramientas actualizadas al último nivel. Para ello tenemos que hacer uso de un Dockerfile, donde detallaremos como se construirá nuestra nueva imagen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

FROM kalilinux/kali:latest

MAINTAINER [email protected]



RUN apt update

RUN apt upgrade -y

RUN apt install iputils-ping git nmap wget zip whatweb net-tools curl nano proxychains privoxy -y

ADD proxychains.conf /etc/

ADD config /etc/privoxy/

ENV http_proxy "127.0.0.1:8118"

ENV https_proxy "127.0.0.1:8118"

ENTRYPOINT service privoxy start && /bin/bash

Como podemos observar en este simple ejemplo, que podemos descargar desde aquí, le indicamos una imagen base, actualizamos los paquetes, instalamos algunas aplicaciones desde el repositorio, añadimos ficheros de configuración, establecemos variables de entorno. Podríamos también descargar el resto de nuestras herramientas desde GitHub.

En este ejemplo hay algunas opciones que usaremos en prácticas posteriores.

Para crear la imagen de este modo, simplemente tenemos que ejecutar el siguiente comando desde la carpeta que hemos descomprimido con nuestro Dockerfile.

1
2
~:$ docker build --tag "custom/kali" . 

Ahora ya podemos desplegar un entorno limpio y actualizado con nuestras herramientas tanto en cloud, en infraestructura de un cliente o en nuestro equipo local.

Una ventaja de trabajar de este modo es que siempre dispondremos de un entorno controlado y actualizado. Podremos levantar una instancia para cada trabajo, separando los entornos para cada uno de nuestros clientes o trabajos.

También es interesante el hecho que, una vez finalizado el trabajo y recabado la información necesaria, al parar la instancia los datos se eliminan, ayudándonos a cumplir con la GDPR y a no disponer de restos de datos de intrusiones anteriores que ya no sean de nuestro interés.

Anonimizando

Otra opción que puede ser de interés para realizar algunas tareas es la de anonimizar las conexiones que realizamos. Para estar seguros de que tenemos todas las conexiones de nuestro sistema bajo control podemos segmentar la red, de modo que el equipo solo pueda conectar con redes externas mediante un proxy, en este caso tor.

Descargaremos la imagen con el servicio proxy de tor dockerizado que necesitaremos para la práctica.

1
2
3
4
5
6
7
8
9
10
11
12
~:$ docker pull peterdavehello/tor-socks-proxy

~:$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

kalilinux/kali latest 4a681ae9009a 7 days ago 124MB

my/kali latest 49f382139b02 22 seconds ago 356MB

peterdavehello/tor-socks-proxy latest 20724e4d3939 7 months ago 20.6MB

Ahora tenemos que crear una nueva red que no dispondrá de acceso a internet y así poder aislar nuestro sistema.

1
2
~:$ docker network create --internal --subnet 10.1.1.0/24 no-internet

Podemos ver las distintas redes de que disponemos con el comando.

1
~:$ docker network ls

Ahora podemos iniciar la instancia de nuestro servicio tor y añadirle posteriormente la nueva red al contenedor, remplazando 912c51969b3b por el id de contenedor creado.

1
2
3
~:$ docker run -d --restart=always --name tor-socks-proxy -p 9150:9150/tcp peterdavehello/tor-socks-proxy:latest

~:$ docker network connect no-internet 912c51969b3b

Para averiguar la IP asignada al servicio ejecutando la siguiente sentencia. Para poder posteriormente configurar el servidor proxy en nuestro equipo kali.

1
~:$ docker network inspect -f '{{range $i, $value := .Containers}} {{if eq $value.Name "tor-socks-proxy" }}{{$value.IPv4Address}}{{end}}{{end}}'  no-internet

Ahora que ya disponemos de la red y el servidor proxy configurados, podemos iniciar nuestro sistema, pero en esta ocasión indicándole que lo despliegue en la nueva red “no-internet”.

1
2
3
4
5
6
7
~:$ docker run --net no-internet -it  custom/kali  /bin/bash 

┌──(root💀c1ab1f86ad44)-[/]

└─# curl ifconfig.me

xxx.xxx.xxx.xxx

Con la ejecución de curl ifconfig.me podemos ver que disponemos de internet y que la ip que nos muestra no es la nuestra.

También podemos realzar un ping a cualquier red externa y comprobar que no disponemos de conexión directa.

Para el resto de las aplicaciones que ejecutemos, tendremos que consultar la documentación para ver si disponen de la opción de uso de proxy, si no es el caso, siempre podemos hacer uso de * proxychains * que tenemos también instalado en nuestro sistema.

Creando laboratorios

Para la creación de laboratorios para realizar pruebas, ya sea con aplicaciones reales en entornos preproducción o para entrenar con nuevas aplicaciones Docker es también una opción excelente.

Podemos desplegar en nuestro equipo local infinidad de servicios y topologías de red que nos permitan de un modo seguro realizar test que necesitemos. Con la ventaja que, si lo hemos realizado todo de forma programática, podremos reiniciar toda la infraestructura de nuevo en caso de ser necesario.

Como ejemplo, pondremos en marcha un router mikrotik, contra el que poder lanzar distintos ataques, pero podemos encontrar también imágenes de WordPress, Joomla u otros sistemas que podamos necesitar para nuestras pruebas.

He elegido la imagen que ejecutaremos a continuación por la cantidad de servicios que levanta, ssh, http, l2tp, … y también, por el uso de docker-compose para iniciar el contenedor.

Para poner la instancia en marcha solo tenemos que ejecutar:

1
2
3
4
5
6
7
~:$ mkdir mkt01

~:$ cd mkt01

~:$ wget https://raw.githubusercontent.com/lordbasex/docker/master/docker-mikrotik/docker-compose.yml -O docker-compose.yml

~:$ docker-compose up -d

No es objeto de este post el profundizar sobre docker-compose, pero sí indicar que es uno de los modos de que dispone Docker para el despliegue de nuestras infraestructuras.

Ahora nos podemos conectar a la instancia de mikrotik (de inicio como admin sin password), crear nuevos usuarios, vpn, … lo que necesitemos para realizar nuestras pruebas.

Conclusiones

El uso de Docker nos facilita tanto las tareas de prevención y defensa, facilitando desplegar sistemas con alta disponibilidad y actualizados, así como las acciones de auditoria, facilitando la creación de entornos de test y disponiendo de entornos configurados para realizar los trabajos.

Es, por lo menos, una solución a tener en cuenta, cuando nos enfrentamos a nuevos retos.

En cuestión de minutos podemos poner en marcha entornos que, de otro modo, nos tomaría mucho más tiempo.

Nos permite en definitiva optimizar tiempo y recursos.

Hasta aquí el post de hoy. Espero haya sido de vuestro interés.
No dudéis en contactar mediante el formulario para hacerme llegar vuestros comentarios.