LibBeat en PHP – Creando nuestro «log-shipper».

En mi último proyecto me he visto en la necesidad de enviar datos desde una apliación PHP contra un elasticsearch que tenía montado. Los requisitos del proyecto eran:

  • Insertar trazas operacionales en ElasticSearch
  • Usar el protocolo Beats en un puerto específico
  • Hacerlo en PHP

Qué es ElasticSearch ?

ElasticSearch es un motor de búsqueda basado en Lucene, provee capacidad de búsqueda de texto avanzada, distribuida, y multi tenant. Proporciona fiabilidad, escalabilidad y proporciona múltiples formas de acceso a sus datos. Lucene es una base de datos no relacional (NoSql) de alto rendimineto hecha en Java y orientada a documentos, almacena los documentos en forma de JSON. Habitualmente, cuando se hace referencia a ElasticSearch se habla del stack de elasticsearch (ELK/BELK):

Sigue leyendo

Security Headers en WordPress

Esta breve entrada tratará de enseñar como se debe configurar de manera segura una instalación de wordpress. El requisito para que esto funcione debe ser tener wordpress con un certificado seguro (SSL/TLS) configurado.

¿Qué son los security headers o encabezados/cabeceras de seguridad?

Son extensiones que proporciona el consorcio de W3C para proteger al usuario contra ataques malintencionados al navegador de un cliente. Este tipo de cabeceras son eficaces para bloqeuar recursos de terceros que no se cargan debidamente, o de dominios no confiables. Otras impiden que la web se cargue como un iframe o incrustada dentro de algún dipo de contenedor para evitar clickjacking (robo de clicks).

Una vez sabemos para que son las security headers, deberemos editar el archivo .htaccess de nuestro wordpress:

Y añadir el siguiente bloque.

Options +FollowSymLinks -Indexes 
php_flag display_errors Off
php_flag session.cookie_httponly on
php_flag session.cookie_secure on

RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]
RewriteRule ^(.*)$ - [F,L]

SetEnvIf Host ^www.bitsdelocos.es$ is_main_domain
	Header set X-Content-Type-Options nosniff env=is_main_domain
	Header set X-XSS-Protection "1; mode=block" env=is_main_domain
	Header unset X-Powered-By env=is_main_domain
	Header unset X-Pingback env=is_main_domain
	Header unset SERVER env=is_main_domain
	Header set Content-Security-Policy "default-src 'self' https: data: wss: 'unsafe-inline' 'unsafe-eval';" env=is_main_domain
	Header set strict-transport-security "max-age=300; preload" env=is_main_domain

	

Las 4 primeras líneas impiden que se listen archivos en las carpetas que no poseen ningun index.php que cargue por defecto, se muestren errores que pueden exponer información sensible del servidor al haber un error o que se obtenga información de debug con los métodos trace y track del servidor apache.

La línea de SetEnvIf es útil si tenemos subdominios sin SSL y no queremos que esta configuración se herede en ellos, en caso de que todo esté securizado se puede eliminar y quitar «env=is_main_domain» de las demás.

Con estas modificaciones se consigue añadir los headers necesarios para poder tener un wordpress seguro en la capa de «navegador», y ocultar información sensible del servidor web que pudiera dar pistas a un atacante de nuestra infraestructura.


Automatizando ACLs en SQUID

Buenas noches en esta entrada os traigo una forma muy sencilla de automatizar el uso de SQUID como proxy de nagevación temporal.

¿Qué es un proxy de navegación?I

Un proxy, o servidor proxy, en una red informática, es un servidor —programa o dispositivo—, que hace de intermediario en las peticiones de recursos que realiza un cliente (A) a otro servidor (C) (Wikipedia).

Proxy inverso/ Reverse Proxy
Arquitectura de un proxy inverso
Sigue leyendo

Shaping con nginx: Limitando CPS (II)

Hace unos días, se me planteó el problema de limitar las CPS (conexiones por segundo a un servicio de APIs externo), por lo que mi primera idea fue limitarlo en el proxy de salida de los servidores (SQUID). Pero eso implicaba cambiar y tunear las IPtables de una forma poco dinámica ya que si el proveedor está en una CDN habría que montar un proceso de actualización de reglas,.. o bien limitarlo para todas las salidas externas del proxy con lo que no resultaba ser una buena opción así que seguí buscando,… en este caso encontré nginx como proxy inverso con el módulo limit_req_zone que permite hacer rate limiting de peticiones.

Siguiendo el esquema de la entrada anterior (Shaping con Iptables: Limitando CPS):

Y la misma arquitectura de pruebas:

Nombre del Servidor IP Descripción
shaper01 10.112.112.101 Nginx Reverse Proxy
webserver01 10.112.112.102 Servidor web con nginx
server01 10.112.112.106 Envío de tráfico

Para simplificar configuraciones, y la lectura de los scripts se han hecho 2 suposiciones.

  1. Tenemos acceso privilegiado a la máquina (sudo -i) o similar.
  2. En el archivo de hosts (/etc/hosts) de cada máquina se ha añadido lo siguiente:
    10.112.112.101 shaper01
    10.112.112.102 webserver01
    10.112.112.106 server01
    

Para las pruebas se ha habilitado la siguiente zona en nuestro nginx (/etc/nginx/conf.d/rate-limit.conf):

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
    listen       80;
    server_name  shaper01;
    location / {
       limit_req zone=mylimit;
       proxy_set_header Host "webserver01";
       proxy_pass http://webserver01;

    }
}

En esta zona se indica que todas las peticiones con el server_name «shaper01», en la ruta / e hijas se aplicará un rate-limiting de 10r/s, y tras aplicar esta limitación serán reenviadas las peticiones contra el servidor webserver01.

El único cambio que hay que hacer en el programa cliente es la url dónde apuntarán sus peticiones, en este caso, se deberán abrir contra el servidor shaper01 en lugar del endpoint de la API.

Las pruebas se han lanzado con curl igual que en la entrada anterior:

while [ 1 ]; do curl shaper01 -s > /dev/null; done

Tras analizar los resultados del nginx del server web, podemos afirmar que está funcionando el rate-limiting.

Conexiones Por segundo usando nginx

Shaping con Iptables: Limitando CPS

Buenas noches, después de mucho tiempo sin pasarme por aquí, esta noche os traigo una pequeña entrada para ver como se puede configurar un rate limiting (shaping) en función de las conexiones por segundo en lugar del por ancho de banda (bandwidth).

Durante el transcurso de esta semana, me han consultado si se podría limitar el consumo de una API REST de un proveedor externo a priori no debería ser mucho problema, cuando te piden esto lo primero que piensas es en limitar el ancho de banda consumido en un packetshaper/firewall aplicando políticas de QoS. Pero esta vez, se solicitó que se limitara por transacciones por segundo permitidas. Tras revisarlo con los compañeros nunca habíamos montado nada así por lo que me he dispuesto a investigar un poco más y he llegado la solución que os contaré en este post.

En la siguiente imagen se describe la arquitectura inicial, en el recuadro rojo se muestra que existen N instancias de una aplicación que competirán por 10 conexiones por segundo contra la API externa (verde).


Sigue leyendo

Integración OSSIM – Elasticsearch

Qué es ossim?

El software de seguridad OSSIM, del inglés Open Source Security Information Management, es un conjunto de herramientas de seguridad (recogida de logs, monitorización, escaneo de vulnerabilidades,…) orquestadas para conseguir una solución de seguridad capaz de correlacionar y detectar eventos de seguridad y vulnerabilidades en una infraestructura determinada.

Tras haber gestionado ossim, me he dado cuenta que la integración de OSSIM con el mundo exterior es algo complicada.. expresiones regulares, creación de nuevos plugins, tener que pasar siempre por syslog,… Para evitar estos problemas se ha desarrollado un nuevo datasource de ossim para permitir la integración de OSSIM con elasticsearch.

El código se encuentra en mi repositorio público:

https://github.com/berni69/ossim-agent-elasticsearch

El código que se debe añadir a ossim es:

ParserElastic.py
ElasticDetector.py

Además se debe modificar el componente Agent.py (línea 559 aprox) para añadir un nuevo tipo de datasource.

                elif plugin.get("config", "source") == "elasticsearch":
                    parser = ParserElastic(self.conf, plugin, None)
                    parser.start()
                    self.detector_objs.append(parser)

Para que esto funcione se debe añadir la librería de elasticsearch para python:

pip install elasticsearch

Ejemplo de configuración:

https://raw.githubusercontent.com/berni69/ossim-plugins-elasticsearch/master/elasticsearch-example.cfg