Ir al contenido principal

Cómo proteger tus APIs instalando y configurando ModSecurity en Nginx

En nuestro día a día nuestro equipo DevOps construye multitud de arquitecturas para proporcionar una base sólida a las integraciones y desarrollos posteriores. Otras veces nuestro trabajo es revisar arquitecturas existentes, reorganizar y proponer mejoras, la mayoría de ocasiones la seguridad en el perímetro es un punto a reforzar. Por eso, en este artículo, os contaremos algunas de las mejoras que solemos ofrecer por defecto en la mayoría de situaciones y se explicará cómo proteger tus APIs instalando y configurando ModSecurity en Nginx.

Glosario de términos: Hardening, Red Tor, User Agent y WAF

A continuación se definirán algunos de los términos de los que iremos hablando durante el artículo:

Bastionado o Hardening

Bastionado o Hardening es el proceso de endurecimiento de las configuraciones por defecto que traen los sistemas operativos con el objetivo de mejorar la seguridad, evitar escalada de privilegios, evitar vulnerabilidades, servicios o puertos expuestos sin uso.

Red Tor

Red Tor es una red creada por software creada sobre la red de internet, usa encriptaciones, VPN  y saltos entre nodos de esa red para proporcionar anonimato, suele ser usada por los piratas informáticos para ocultar su IP, esta red puede ser usada con fines simplemente de anonimato e investigación o con fines no tan lícitos.

User Agent

User Agent se refiere al identificador donde se muestra información del servicio y la versión, suele estar en las cabeceras de los servicios, escáneres de software, servidores web y servicios en general.

WAF

Web Application Firewall (WAF) es un firewall de aplicaciones, al igual que un firewall de red trabaja filtrando los paquetes en sus políticas o reglas, un WAF está especializado en la capa de aplicación, filtrando de manera minuciosa el tráfico a nivel de aplicación, pudiendo detectar los ataques y estableciendo filtro o reglas  personalizadas o definidas en el estándar OWASP.

Casos de uso o ámbito de aplicación

Generalmente el contexto siempre es el mismo o muy similar, servidores web o máquinas virtuales Linux/Windows que hacen de entrada a la plataforma como servidor web  de aplicaciones, proxy o balanceador.

El factor común es que normalmente estos sistemas operativos se encuentran por defecto, algo nada recomendable en un equipo que hace frontera entre internet y la nuestra red interna.

La realidad que nos encontramos

Hoy día ya casi todas las organizaciones tienen un firewall de red o NGF y una zona DMZ, lo que suele ocurrir es que el firewall de red si no se han ajustado muy bien las políticas se suele  ignorar los servicios que están expuestos a nivel de aplicación, lo que quiero decir es que no está debidamente acotado  al servicio, host u aplicación que estamos exponiendo, y es que lo correcto sería aplicar las firmas del sistema operativo (Ubuntu Linux, Windows server etc…), después aplicar las  firmas del servicio (Apache, Nginx, ISS), después las firmas de la aplicación.

Una vez finalizados estos ajustes podemos añadir el módulo  de WAF básico, algunos firewall traen este módulo, este módulo no actúa con la misma efectividad que un WAF, principalmente porque no lo es, pero añade alguna mejora, por otro lado tenemos las políticas anti DDoS, en este aspecto si vuestro firewall tiene esa opción, es recomendable habilitar, sabemos que estas funciones son eso funciones extras y que no serán tan efectivos como hardware o host dedicado. 

En algunas organizaciones nos encontramos con el escenario anterior y realizamos nuestras recomendaciones, además cuando entramos a desplegar nuestra arquitectura o auditamos o rectificamos la arquitectura del cliente añadimos algunas  mejoras de base.

Procedimiento realizado

  1. En primer lugar generamos un informe de pre-bastionado en todos los host que forman parte de la arquitectura o proyecto.
  2. En segundo lugar ponemos en común con el cliente el resultado, le hacemos nuestras recomendaciones  y vemos hasta donde quiere llegar.
  3. El proceso de Hardening o bastionado varía por sistema operativo y existen varias guías o herramientas para gestionarlo como por ejemplo CIS Benchmarks, nosotros solemos preparar procesos automatizados para el bastionado de grandes números de activos, aunque previamente desarrollamos y probamos la automatizacion del hardering, después podemos usar Ansible o combinar con Bash o PowerShell según el caso.

Al final se trata de incorporar el punto de vista de la seguridad de manera transversal en todo el flujo de trabajo y en todas las áreas.

Y es que esto, no es opcional si queremos estar al día y proteger nuestros sistemas y aplicaciones, es aquí donde aparece el perfil o metodología DevSecOps.

Devops y automation: Seguridad

DevOps + Automation = Security

Nginx protegiendo aplicaciones

Como mencionamos anteriormente nosotros incorporamos por defecto unas mejoras de seguridad sobre el bastionado comentado anteriormente y sobre el proxy o balanceador.

En este apartado vamos a comentar las mejoras técnicas que añadimos a NGINX y es que con NGINX tenemos la opción del  WAF  open source llamado modsecurity  o su versión de pago NGINX+ llamada WAF.

Para poder hacer uso de modsecurity necesitamos compilar la última versión de Nginx preparándolo para usar el modulo modsecurity.

En esta ocasión daremos algunas instrucciones y requerimientos para Centos 8/Redhat.

Paquetes y repositorios necesarios 

A continuación instalaremos  los paquetes necesarios para una distribución Redhat/Centos 8:

# dnf update
dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm -y


dnf install gcc-c++ flex bison yajl curl-devel zlib-devel pcre-devel autoconf automake git curl make libxml2-devel pkgconfig libtool httpd-devel redhat-rpm-config wget openssl openssl-devel nano -y

dnf --enablerepo=powertools install doxygen yajl-devel -y
dnf --enablerepo=remi install geoip-devel -y
yum install geoip-devel -y

Instalación y compilación modsecurity 

Ahora instalaremos modsecurity, para ello vamos a compilar, podéis seguir las siguientes instrucciones:

#clonaremos repo de modsecurity para nginx en el dir opt
cd /opt/ && git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity

# Entramos en el directorio bajamos la última versión y compilamos el módulo.
cd ModSecurity
git submodule init
git submodule update
./build.sh && ./configure

make && make install
 
# bajamos modsecurity-nginx
cd /opt
git clone https://github.com/SpiderLabs/ModSecurity-nginx.git

Instalación y compilación de Nginx con compatibilidad modsecurity 

Descargamos la última versión estable de la página oficial, descomprimimos y compilamos e instalamos:

wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar -xvzf nginx-1.18.0.tar.gz
cd /opt/nginx-1.18.0

./configure --user=nginx --group=nginx --with-pcre-jit --with-debug --with-http_ssl_module  --with-http_realip_module --add-module=/opt/ModSecurity-nginx

Puesta en funcionamiento de modsecurity

Ejemplo de archivo de configuración Nginx habilitando modsecurity:

#Plantilla ejemplo  /usr/local/nginx/conf/nginx.conf

user  nginx;
worker_processes  1;
pid  /run/nginx.pid;
events {
     worker_connections  1024;
 }

 http {
     include	  mime.types;
     default_type  application/octet-stream;
     sendfile        on;
     keepalive_timeout  65;
     server {
         listen       80;
         server_name  your-server-ip;
         modsecurity  on;
         modsecurity_rules_file  /usr/local/nginx/conf/modsecurity.conf;
         access_log  /var/log/nginx/access.log;
         error_log  /var/log/nginx/error.log;
         location / {
             root   html;
             index  index.html index.htm;
         }
         error_page   500 502 503 504  /50x.html;
         location = /50x.html {
             root   html;

Recargando y testeando la configuración

Ahora aplicaremos cambios para configurar modsecurity, validamos que la configuración es correcta y reiniciamos el servicio:

#Configurando modsecurity en nginx

sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/g' /usr/local/nginx/conf/modsecurity.conf
sed -i 's/\/var\/log\/modsec_audit.log/\/var\/log\/nginx\/modsec_audit.log/g' /usr/local/nginx/conf/modsecurity.conf


#Testeamos la config
nginx -t

# Habilitamos el demonio e iniciamos el servicio nginx
systemctl daemon-reload
systemctl start nginx
systemctl enable --now nginx
systemctl status nginx

Configurando modsecurity con OWASP rules

Descargamos las reglas de OWASP desde su repositorio y las incluiremos en la configuración de modsecurity:

git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /usr/local/nginx/conf/owasp-crs
mv /usr/local/nginx/conf/owasp-crs/crs-setup.conf.example /usr/local/nginx/conf/owasp-crs/crs-setup.conf

echo "Include owasp-crs/crs-setup.conf" >> /usr/local/nginx/conf/modsecurity.conf
echo "Include owasp-crs/rules/*.conf" >> /usr/local/nginx/conf/modsecurity.conf

nginx -t 

# si todo va bien reiniciamos.
systemctl restart nginx

Bloqueando accesos desde la Red Tor

En este apartado explicaremos la capacidad que tiene Nginx de bloquear una IP para bloquear su acceso.

Para bloquear accesos a determinadas IP en Nginx la sintaxis es la siguiente.

deny 192.168.1.2;
deny 192.168.1.3;

Ahora que ya conocéis cómo bloquear listados de IP, ahora desde la fuente torproject podemos descargar el listado de los nodos de salida.

Si creamos un  script para la descarga del listado de IP y formateamos la salida podemos tener un listado similar a este:

deny 104.244.73.215;
deny 198.98.62.107;
deny 104.244.79.203;
deny 209.141.55.90;
deny 209.141.41.214;
deny 143.110.236.82;
deny 93.95.227.227;

Podemos guardar la salida anterior en un archivo, por ejemplo include /opt/nginx_deny_tor.txt;

Es recomendable automatizar el paso anterior para mantener actualizado el listado, podríamos hacerlo con CRONTAB.

Ahora si vamos a la documentación de Nginx podemos observar que entre sus muchas opciones una permite  bloquear un listado de IP, podemos incluir el listado tal y como se muestra en el ejemplo:

 location / {
   include /opt/nginx_deny_tor.txt;
   #…...etc...
}

Bloqueando escáneres de vulnerabilidades  o similares vía user agent

location / {
   include /opt/nginx_deny_tor.txt;
   if ($http_user_agent ~* (^w3af.sourceforge.net|dirbuster|nikto|wpscan|SF|sqlmap|fimap|nessus|whatweb|Openvas|jbrofuzz|libwhisker|webshag)) {
        return 444;
   }

Como podéis ver en el apartado anterior añadimos a la configuración location/un condicional basado en el User Agent, si coincide con una de las opciones se cerrará la conexión. 

Podemos modificar nuestro user agent en nuestro navegador firefox con esta herramienta llamada User Agent Switcher para realizar pruebas.

Conclusiones

  • Hemos comentado la importancia y algunas herramientas de bastionado de sistemas.
  • Hemos comentado cómo podemos añadir modsecurity a Nginx como WAF.
  • Hemos comentado cómo bloquear conexiones desde la Red Tor.
  • Hemos explicado cómo cerrar la conexión a clientes con User Agent no deseado.