Instalar ModSecurity con Apache en un contenedor Docker
ModSecurity es un cortafuegos de aplicaciones web (WAF) gratuito, de código abierto, y el más popular, que protege tu aplicación web contra una amplia gama de ataques de capa 7. Ha sido diseñado para monitorizar, registrar y filtrar las peticiones del servidor web Apache. Viene con un conjunto de reglas básicas que detecta y detiene varios ataques, como la inyección SQL, el cross-site scripting, los troyanos, los agentes de usuario malintencionados, el secuestro de sesiones y otros.
En este tutorial, te mostraré cómo instalar ModSecurity 3 con Apache dentro de un contenedor Docker.
Requisitos
- Un servidor con Ubuntu 20.04.
- Una contraseña de root configurada en tu servidor.
Cómo empezar
En primer lugar, se recomienda actualizar tu sistema a la última versión. Puedes actualizarlo con el siguiente comando:
apt-get update -y
Una vez que tu sistema esté actualizado, necesitarás instalar algunas dependencias en tu sistema. Puedes instalarlas todas con el siguiente comando:
apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common -y
Una vez instaladas todas las dependencias, puedes pasar al siguiente paso.
Instalar Docker
A continuación, tendrás que instalar el CE de Docker en tu sistema. Por defecto, la última versión de Docker no está incluida en el repositorio por defecto de Ubuntu. Así que tendrás que añadir el repositorio oficial de Docker al APT.
Primero, descarga y añade la clave GPG de Docker con el siguiente comando:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
A continuación, añade el repositorio Docker CE a la lista de fuentes de APT con el siguiente comando:
echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -sc) stable" > /etc/apt/sources.list.d/docker-ce.list
Una vez añadido el repositorio, actualiza el repositorio con el siguiente comando:
apt-get update -y
Una vez actualizado el repositorio, instala la última versión de Docker CE con el siguiente comando:
apt-get install docker-ce -y
Después de instalar Docker CE, verifica la versión instalada de Docker CE con el siguiente comando:
docker --version
Deberías obtener la siguiente salida:
Docker version 20.10.6, build 370c289
También puedes comprobar el estado del servicio Docker con el siguiente comando:
systemctl status docker
Deberías obtener la siguiente salida:
? docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2021-05-16 06:49:29 UTC; 38s ago TriggeredBy: ? docker.socket Docs: https://docs.docker.com Main PID: 8964 (dockerd) Tasks: 8 Memory: 40.6M CGroup: /system.slice/docker.service ??8964 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.365433228Z" level=warning msg="Your kernel does not support swap memory li> May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.365916961Z" level=warning msg="Your kernel does not support cgroup blkio w> May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.366112111Z" level=warning msg="Your kernel does not support cgroup blkio w> May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.366653374Z" level=info msg="Loading containers: start." May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.498790388Z" level=info msg="Default bridge (docker0) is assigned with an I> May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.576691602Z" level=info msg="Loading containers: done." May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.610542206Z" level=info msg="Docker daemon" commit=8728dd2 graphdriver(s)=o> May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.611668583Z" level=info msg="Daemon has completed initialization" May 16 06:49:29 ubuntu2004 systemd[1]: Started Docker Application Container Engine. May 16 06:49:29 ubuntu2004 dockerd[8964]: time="2021-05-16T06:49:29.690496888Z" level=info msg="API listen on /run/docker.sock" lines 1-21/21 (END)
Una vez que hayas terminado, puedes pasar al siguiente paso.
Crear un Dockerfile para ModSecurity
A continuación, tendrás que crear un Dockerfile para instalar el ModSecurity dentro del contenedor de Ubuntu.
Primero, cambia el directorio a /opt y crea un archivo modsec_rules.conf con el siguiente comando:
cd /opt
nano modsec_rules.conf
Añade las siguientes líneas:
Include "/etc/apache2/modsecurity.d/modsecurity.conf" Include "/etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf" Include "/etc/apache2/modsecurity.d/owasp-crs/rules/*.conf"
Guarda y cierra el archivo y luego crea otro archivo con el siguiente comando:
nano 000-default.conf
Añade las siguientes líneas:
<VirtualHost *:80> modsecurity on modsecurity_rules_file /etc/apache2/modsecurity.d/modsec_rules.conf ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Guarda y cierra el archivo cuando hayas terminado. Dockerfile copiará los archivos anteriores al contenedor Docker durante el proceso de construcción.
Por último, crea un archivo Dockerfile con el siguiente comando
nano Dockerfile
Añade las siguientes líneas:
# Install Modsecurity in a Docker container; FROM ubuntu:latest ARG DEBIAN_FRONTEND=noninteractive # update/upgrade your system RUN apt-get update -y # Install Required Dependencies RUN apt-get install -y g++ flex bison curl apache2-dev \ doxygen libyajl-dev ssdeep liblua5.2-dev \ libgeoip-dev libtool dh-autoreconf \ libcurl4-gnutls-dev libxml2 libpcre++-dev \ libxml2-dev git wget tar apache2 # Download LibModsecurity RUN wget https://github.com/SpiderLabs/ModSecurity/releases/download/v3.0.4/modsecurity-v3.0.4.tar.gz # Extract the Downloaded File RUN tar xzf modsecurity-v3.0.4.tar.gz && rm -rf modsecurity-v3.0.4.tar.gz # Compile and Install LibModsecurity RUN cd modsecurity-v3.0.4 && \ ./build.sh && ./configure && \ make && make install # Install ModSecurity-Apache Connector RUN cd ~ && git clone https://github.com/SpiderLabs/ModSecurity-apache RUN cd ~/ModSecurity-apache && \ ./autogen.sh && \ ./configure --with-libmodsecurity=/usr/local/modsecurity/ && \ make && \ make install # Load the Apache ModSecurity Connector Module RUN echo "LoadModule security3_module /usr/lib/apache2/modules/mod_security3.so" >> /etc/apache2/apache2.conf # Configure ModSecurity RUN mkdir /etc/apache2/modsecurity.d && \ cp modsecurity-v3.0.4/modsecurity.conf-recommended /etc/apache2/modsecurity.d/modsecurity.conf && \ cp modsecurity-v3.0.4/unicode.mapping /etc/apache2/modsecurity.d/ && \ sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/apache2/modsecurity.d/modsecurity.conf ADD modsec_rules.conf /etc/apache2/modsecurity.d/ # Install OWASP ModSecurity Core Rule Set (CRS) on Ubuntu RUN git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /etc/apache2/modsecurity.d/owasp-crs && \ cp /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf.example /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf # Activate ModSecurity RUN mv /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/000-default.conf.old ADD 000-default.conf /etc/apache2/sites-available/ EXPOSE 80 CMD apachectl -D FOREGROUND
Guarda y cierra el archivo cuando hayas terminado.
El archivo anterior descargará la imagen de Ubuntu, instalará todas las dependencias, descargará el ModSecurity, lo compilará y configurará Apache para que funcione con el ModSecurity.
En este punto, el Dockerfile está listo. Ahora puedes pasar al siguiente paso.
Construye la imagen de ModSecurity de Apache e inicia el contenedor
Ahora, cambia el directorio a /opt y construye la imagen Docker para Apache ModSecurity con el siguiente comando:
cd /opt
docker build .
Una vez completado el proceso de construcción, deberías obtener la siguiente salida:
Step 13/17 : RUN git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /etc/apache2/modsecurity.d/owasp-crs && cp /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf.example /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf ---> Running in 00dfa2a5cd23 Cloning into '/etc/apache2/modsecurity.d/owasp-crs'... Removing intermediate container 00dfa2a5cd23 ---> b38c1d874d2f Step 14/17 : RUN mv /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/000-default.conf.old ---> Running in 12c9e6d2c559 Removing intermediate container 12c9e6d2c559 ---> 899e26019297 Step 15/17 : ADD 000-default.conf /etc/apache2/sites-available/ ---> eb11751afd6c Step 16/17 : EXPOSE 80 ---> Running in 2f4ba47e2b66 Removing intermediate container 2f4ba47e2b66 ---> dd59b0ac7c7c Step 17/17 : CMD apachectl -D FOREGROUND ---> Running in 98b8cc77df0f Removing intermediate container 98b8cc77df0f ---> f603dbc38018 Successfully built f603dbc38018
Ahora puedes listar todas las imágenes Docker con el siguiente comando:
docker images
Deberías obtener el siguiente resultado:
REPOSITORY TAG IMAGE ID CREATED SIZEf603dbc38018 32 seconds ago 2.48GB ubuntu latest 7e0aa2d69a15 3 weeks ago 72.7MB
Ahora, elige el primer id de imagen de la salida anterior e inicia el contenedor Apache ModSecurity con el siguiente comando:
docker run --name modsec-apache -ditp 80:80 f603dbc38018
Deberías obtener el siguiente resultado:
40eb0e77e61635c3cee2bfaffbd9489bc7d20aa3e1befb52749de079aaadb528
Ahora puedes verificar el contenedor en ejecución con el siguiente comando:
docker ps
Deberías obtener la siguiente salida:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 40eb0e77e616 f603dbc38018 "/bin/sh -c 'apachec…" 17 seconds ago Up 15 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp modsec-apache
Como puedes ver, el contenedor ModSecurity está iniciado y escuchando en el puerto 80.
Verificar ModSecurity
Llegados a este punto, el contenedor ModSecurity se está ejecutando. Ahora, es el momento de comprobar si las reglas de ModSecurity bloquean las peticiones maliciosas o no.
Para ello, abre tu terminal y ejecuta el siguiente comando:
curl localhost?doc=/bin/ls
Deberías ver la siguiente salida:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access this resource.</p> <hr> <address>Apache/2.4.41 (Ubuntu) Server at localhost Port 80</address> </body></html>
Deberías ver el error«403 Forbidden«. Porque ModSecurity ha bloqueado la petición anterior.
También puedes consultar el registro de Apache para obtener más información.
Para ello, primero conéctate al contenedor con el siguiente comando:
docker exec -it modsec-apache /bin/bash
Una vez conectado, deberías obtener el siguiente shell:
root@40eb0e77e616:/#
Ahora, comprueba el registro de Apache con el siguiente comando:
tail -f /var/log/apache2/error.log
Deberías ver que ModSecurity ha bloqueado la petición maliciosa:
[Sun May 16 07:24:54.456327 2021] [mpm_event:notice] [pid 15:tid 140204464299072] AH00489: Apache/2.4.41 (Ubuntu) configured -- resuming normal operations [Sun May 16 07:24:54.456352 2021] [core:notice] [pid 15:tid 140204464299072] AH00094: Command line: '/usr/sbin/apache2 -D FOREGROUND' [Sun May 16 07:25:36.680515 2021] [:error] [pid 16:tid 140204216108800] [client 172.17.0.1:45298] ModSecurity: Warning. Matched "Operator `PmFromFile' with parameter `unix-shell.data' against variable `ARGS:doc' (Value: `/bin/ls' ) [file "/etc/apache2/modsecurity.d/owasp-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [line "496"] [id "932160"] [rev ""] [msg "Remote Command Execution: Unix Shell Code Found"] [data "Matched Data: bin/ls found within ARGS:doc: /bin/ls"] [severity "2"] [ver "OWASP_CRS/3.2.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-shell"] [tag "platform-unix"] [tag "attack-rce"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION"] [tag "WASCTC/WASC-31"] [tag "OWASP_TOP_10/A1"] [tag "PCI/6.5.2"] [hostname "172.17.0.2"] [uri "/"] [unique_id "162114993662.860969"] [ref "o1,6v10,7t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase"]
Conclusión
Enhorabuena! has instalado con éxito ModSecurity dentro del contenedor Docker. Espero que ahora tengas suficientes conocimientos para implementar esta solución en el entorno Docker. No dudes en preguntarme si tienes alguna duda.