Docker es un proyecto OpenSource. Con Docker podemos utiliizar los contenedores como máquinas virtuales muy livianas y modulares.
📌¿Como instalar Docker?
Para instalar Docker en nuestros equipos Linux solo tendremos que poner lo siguiente:
Debian/Derivados:
❯ sudo apt install docker.io
ArchLinux/Derivados:
❯ sudo pacman -S docker
Fedora/Derivados:
❯ sudo dnf install docker
📌Como usar Docker
Si queremos ver las imágenes de Docker que tengamos podremos hacer un:
❯ docker images
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 35a88802559d 7 weeks ago 78.1MB
Si queremos sacar una imagen ya hecha de Ubuntu,Debian,etc… con docker pull podremos:
docker pull debian:latest
Si queremos listar los contenedores que tengamos podremos emplear docker ps:
❯ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fc58d5436a68 ubuntu "/bin/bash" 3 hours ago Up 3 hours focused_mayer
Con docker ps de manera predeterminada solo nos muestra los contenedores que estén activos, si queremos ver todos los contenedores tendremos que agregar el parámetro -a o --all:
❯ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fc58d5436a68 ubuntu "/bin/bash" 3 hours ago Up 3 hours focused_mayer
27fc4260aae8 debian "/bin/bash" 2 hours ago Exited (137) 3 seconds ago agitated_jennings
Si queremos borrar contenedores usaremos docker rm:
Para emplear bien este comando seguiremos esta estructura:
docker rm IDCONTENEDOR
Recordemos que podemos usar el docker ps -a para ver los ID de todos los contenedores dando si están activos o no podemos emplear docker ps con el parámetro -a o --all:
❯ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7050ab52f603 debian "bash" 2 minutes ago Exited (137) About a minute ago agitated_jennings
fc58d5436a68 ubuntu "/bin/bash" 3 hours ago Up 3 hours focused_mayer
Si queremos borrar todos los contenedores a la vez podemos usar los parámetros -a y -q, el -q nos servirá para pillar solo el CONTAINER ID:
Usamos el --force para forzar que se elimine tanto contenedores inactivos o activos.
❯ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Esto mismo podemos aplicarlo a las imágenes, solo con la diferencia que no usaremos rm emplearemos rmi que nos servirá para eliminar imágenes Docker. Al igual que con docker ps -aq podemos usarlo con images:
Para instalar OpenSSH tendremos que poner lo siguiente:
root@fc58d5436a68:/# apt install ssh
Una vez ya tengamos ssh instalado pondremos lo siguiente para iniciar el servicio:
root@fc58d5436a68:/# service ssh start
* Starting OpenBSD Secure Shell server sshd [ OK ]
Para confirmar podemos hacerle un escaneo nmap y ver si lo tiene abierto:
❯ nmap -p- --open -n -Pn -vvv 172.17.0.2
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-28 06:42 EDT
Initiating ARP Ping Scan at 06:42
Scanning 172.17.0.2 [1 port]
Completed ARP Ping Scan at 06:42, 0.04s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 06:42
Scanning 172.17.0.2 [65535 ports]
Discovered open port 22/tcp on 172.17.0.2
Completed SYN Stealth Scan at 06:42, 1.05s elapsed (65535 total ports)
Nmap scan report for 172.17.0.2
Host is up, received arp-response (0.0000070s latency).
Scanned at 2024-07-28 06:42:07 EDT for 1s
Not shown: 65534 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 64
MAC Address: 02:42:AC:11:00:02 (Unknown)
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.25 seconds
Raw packets sent: 65536 (2.884MB) | Rcvd: 65536 (2.621MB)
📌Iniciar servicio FTP
Para instalar FTP pondremos lo siguiente:
root@fc58d5436a68:/# apt install vsftpd
Una vez finalizada la instalación iniciaremos su servicio:
root@fc58d5436a68:/# service vsftpd start
* Starting FTP server vsftpd [ OK ]
❯ nmap -p- --open -n -Pn -vvv 172.17.0.2
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-28 06:47 EDT
Initiating ARP Ping Scan at 06:47
Scanning 172.17.0.2 [1 port]
Completed ARP Ping Scan at 06:47, 0.07s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 06:47
Scanning 172.17.0.2 [65535 ports]
Discovered open port 21/tcp on 172.17.0.2
Completed SYN Stealth Scan at 06:47, 0.98s elapsed (65535 total ports)
Nmap scan report for 172.17.0.2
Host is up, received arp-response (0.0000070s latency).
Scanned at 2024-07-28 06:47:51 EDT for 1s
Not shown: 65534 closed tcp ports (reset)
PORT STATE SERVICE REASON
21/tcp open ftp syn-ack ttl 64
MAC Address: 02:42:AC:11:00:02 (Unknown)
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.19 seconds
Raw packets sent: 65536 (2.884MB) | Rcvd: 65536 (2.621MB)
Si por ejemplo queremos hacer una máquina donde está habilitado el anonymous tendremos que editar con nano que tendremos que instalarlo nosotros porque en el contenedor ubuntu no viene y con nano editaremos el /etc/vsftpd.conf:
Instalamos nano:
apt install nano
Editamos el archivo vsftpd.conf y buscaremos la linea que ponga:
# Allow anonymous FTP? (Disabled by default).
anonymous_enable=NO
Y cambiaremos el anonymous_enable=NO por:
anonymous_enable=YES
Guardamos y reiniciamos el servicio:
root@fc58d5436a68:/etc# service vsftpd restart
* Stopping FTP server [ OK ]
* Starting FTP server vsftpd [ OK ]
Ahora lanzaremos un nmap indicandole el script ftp-anon:
❯ nmap -p21 --script=ftp-anon 172.17.0.2
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-28 06:54 EDT
Nmap scan report for 172.17.0.2
Host is up (0.000042s latency).
PORT STATE SERVICE
21/tcp open ftp
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
MAC Address: 02:42:AC:11:00:02 (Unknown)
Nmap done: 1 IP address (1 host up) scanned in 0.39 seconds
📌Iniciar servicio Apache2
Para instalar Apache2 pondremos lo siguiente:
root@fc58d5436a68:~# apt install apache2
Una vez finalizada la instalación iniciaremos el servicio:
root@fc58d5436a68:~# service apache2 start
* Starting Apache httpd web server apache2
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message*
Ahora si vamos a nuestro navegador y ponemos la IP del contenedor podremos ver la plantilla predeterminada de Apache2:
En mi caso he modificado el index.html:
<h1>Blog Pylon - Crea tu CTF en Docker<h1>
<p>Espero que te este gustando!!</p>
📌Iniciar servicio Nginx
Para instalar nginx pondremos lo siguiente:
root@fc58d5436a68:~# apt install nginx
Una vez finalizada la instalación vamos a iniciar el servicio:
root@fc58d5436a68:~# service nginx start
* Starting nginx nginx [ OK ]
Para modificar o crear la web usa la misma ruta que Apache2 que es la /var/www/html.📌Iniciar servicio Nginx
Para instalar nginx pondremos lo siguiente:
root@fc58d5436a68:~# apt install nginx
Una vez finalizada la instalación vamos a iniciar el servicio:
root@fc58d5436a68:~# service nginx start
* Starting nginx nginx [ OK ]
Para modificar o crear la web usa la misma ruta que Apache2 que es la /var/www/html.
⚙️Configuración de usuarios
📌Crear usuarios nuevos
Para crear usuario nuevos podremos usar adduser:
root@fc58d5436a68:~# adduser usuarionuevo
info: Adding user `usuarionuevo' ...
info: Selecting UID/GID from range 1000 to 59999 ...
info: Adding new group `usuarionuevo' (1001) ...
info: Adding new user `usuarionuevo' (1001) with group `usuarionuevo (1001)' ...
info: Creating home directory `/home/usuarionuevo' ...
info: Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for usuarionuevo
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
info: Adding new user `usuarionuevo' to supplemental / extra groups `users' ...
info: Adding user `usuarionuevo' to group `users' ...
Para establecer permisos sudoers a un usuario tendremos que editar el /etc/sudoers y bajaremos hasta la zona donde ponga:
# User privilege specification
root ALL=(ALL:ALL) ALL
Para especificar un permiso sudo, tendremos que seguir la siguiente estructura:
usuario ALL=(usuario o root[ALL:ALL]) /ruta/del/binario/o/lo/que/sea
Por ejemplo yo he creado un usuario llamado sudoersuser que tenga la capacidad de usar nano como root sin necesidad de su credencial:
# User privilege specification
root ALL=(ALL:ALL) ALL
sudoersuser ALL=(root) NOPASSWD: /usr/bin/nano
Si nos convertimos en el usuario y hacemos un sudo -l podremos ver el permiso que le hemos especificado en el /etc/sudoers:
sudoersuser@fc58d5436a68:~$ sudo -l
Matching Defaults entries for sudoersuser on fc58d5436a68:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User sudoersuser may run the following commands on fc58d5436a68:
(root) NOPASSWD: /usr/bin/nano
📌Permisos en Apache2
Cuando creamos una web en apache2 puede ocurrir de que los usuarios puedan acceder a la carpeta images,js,db,etc.... Para impedir esto tendremos que crear un archivo .conf en el directorio de /etc/apache2/sites-enabled, en el veremos un archivo llamado 000-default.conf, lo editaremos y pondremos lo siguiente:
<Directory /var/www/html/images/>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
<Directory /var/www/html/images/>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
Ahora guardaremos esos cambios y reiniciaremos el servicio apache2:
root@e5b9bcc4bcf6:/var/www/html/images# service apache2 restart
* Restarting Apache httpd web server apache2
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
Y todo esto lo podemos configurar para diferentes carpetas:
<Directory /var/www/html/images/>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<Directory /var/www/html/css/>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<Directory /var/www/html/js/>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
⚙️ Configuración de Dockerfile
Ya estamos casi por el final de nuestro CTF, ahora nos toca crear un Dockerfile apuntando a una snapshot o directamente al contenedor docker de la siguiente manera:
FROM snapshot1:latest
Ahora pondremos CMD y le indicaremos ejecutar todos los servicios que tienen que estar activos cuando se despliege nuestro contenedor docker:
FROM snapshot1:latest
CMD service apache2 start && tail -f /dev/null
Veréis que al final de los servicios he puesto tail -f /dev/null esto lo que hace es un bucle infinito apuntando al /dev/null, esto nos ayudara a cuando la persona inicie el contenedor docker los servicios no se apaguen y estén iniciados.
📌 Exportar contenedor a .tar
Emplearemos docker build y el parametro --tag para establecerle un nombre a la imagen:
❯ docker build --tag miprimerctf .
Sending build context to Docker daemon 282.1kB
Step 1/2 : FROM snapshot1:latest
---> 8d230ff6c31a
Step 2/2 : CMD service apache2 start && tail -f /dev/null
---> Running in a2c8c3cd1aba
Removing intermediate container a2c8c3cd1aba
---> d0ba19aba1c4
Successfully built d0ba19aba1c4
Successfully tagged miprimerctf:latest
El . es que le estoy indicando que el archivo Dockerfile se encuentra en el directorio actual donde estoy. Si hacemos un docker images podremos ver la imagen que hemos construido con su respectivo nombre:
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
miprimerctf latest d0ba19aba1c4 About a minute ago 226MB
snapshot1 latest 8d230ff6c31a 10 minutes ago 226MB
ubuntu latest 35a88802559d 7 weeks ago 78.1MB
Ahora es cuando emplearemos docker save para guardar la imagen en un .tar:
❯ docker save -o miprimerctf.tar miprimerctf:latest
❯ ls
Dockerfile miprimerctf.tar
Para comprobar de que todo funciona correcto vamos a descargarnos una maquina al azar de Dockerlabs y utilizaremos su auto_deploy.sh a nuestro archivo .tar:
❯ bash auto_deploy.sh miprimerctf.tar
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
___ ____ ____ _ _ ____ ____ _ ____ ___ ____
| \ | | | |_/ |___ |__/ | |__| |__] [__
|__/ |__| |___ | \_ |___ | \ |___ | | |__] ___]
Se han detectado máquinas de DockerLabs previas, debemos limpiarlas para evitar problemas, espere un momento...
Se han detectado máquinas de DockerLabs previas, debemos limpiarlas para evitar problemas, espere un momento...
Estamos desplegando la máquina vulnerable, espere un momento.
Máquina desplegada, su dirección IP es --> 172.17.0.3
Presiona Ctrl+C cuando termines con la máquina para eliminarla
Ahora le haremos un escaneo nmap para ver si esta el puerto 80 abierto que es el que hemos establecido iniciando el servidor apache2 en el Dockerfile:
❯ nmap -p- --open -n -Pn -vvv 172.17.0.3
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-28 10:15 EDT
Initiating ARP Ping Scan at 10:15
Scanning 172.17.0.3 [1 port]
Completed ARP Ping Scan at 10:15, 0.06s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 10:15
Scanning 172.17.0.3 [65535 ports]
Discovered open port 80/tcp on 172.17.0.3
Completed SYN Stealth Scan at 10:15, 1.11s elapsed (65535 total ports)
Nmap scan report for 172.17.0.3
Host is up, received arp-response (0.0000070s latency).
Scanned at 2024-07-28 10:15:50 EDT for 1s
Not shown: 65534 closed tcp ports (reset)
PORT STATE SERVICE REASON
80/tcp open http syn-ack ttl 64
MAC Address: 02:42:AC:11:00:03 (Unknown)
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.31 seconds
Raw packets sent: 65536 (2.884MB) | Rcvd: 65536 (2.621MB)
📝 Creación del Writeup
Ya habiendo comprobado que la máquina funciona bien y está todo correcto, nos toca lo último que es el writeup. Os comparto una estructura en PDF de un writeup para Dockerlabs que es el que yo empleo:
👋 Despedida
Espero que hayáis aprendido en como crear un CTF en Docker, tener en cuenta que ciertas cosas como los servicios se puede hacer en un Ubuntu Server y intentar crear una máquina para otra plataforma. Este es un blog que me ha parecido muy bueno crearlo para ayudar a la gente que quiere crear su CTF sin tener idea y obtenga cierta base con este blog. Adelanto que subiré un blog nuevo donde ensenaré como configuro una máquina desde el minuto 0 hasta que la tengo creada.
Y nos descargará la última versión de la imagen de Debian que exista en Docker. Podemos sacar más imágenes en
Si queremos modificar la web tendremos que ir al /var/www/html y ahi dentro podremos meter una o crear a mano la web:
Esta es una de las partes más importantes si queremos publicar el CTF en la plataforma de que es que tendremos que construir una nueva imagen con el Dockerfile que hemos creado con los parámetros indicados de iniciar los servicios necesarios, así que vamos a construir una imagen nueva desde el Dockerfile llamada miprimerctf claramente no es necesario poner ese nombre, vosotros poner el que más os guste para el CTF: