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 | ~:$ docker images |
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 | ~:$ docker run -ti kalilinux/kali /bin/bash |
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 | ~:$ docker ps |
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 | ~:$ docker images |
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 |
|
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 | ~:$ 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 | ~:$ docker pull peterdavehello/tor-socks-proxy |
Ahora tenemos que crear una nueva red que no dispondrá de acceso a internet y así poder aislar nuestro sistema.
1 | ~:$ 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 | ~:$ docker run -d --restart=always --name tor-socks-proxy -p 9150:9150/tcp peterdavehello/tor-socks-proxy:latest |
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 | ~:$ docker run --net no-internet -it custom/kali /bin/bash |
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 | ~:$ mkdir mkt01 |
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.