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

Mantén tus dispositivos actualizados con Ansible

Si te gusta cacharrear como a mi, al final terminas teniendo varios dispositivos conectados a la red de tu casa y otros tantos distribuidos en el cloud, una de las tareas más tediosas a las que te puedes enfrentar es irlos actualizado a medida que pasa el tiempo. No a todos estos dispositivos me conecto habitualmente por lo que no siempre recuerdo actualizarlos, para solucionar esto he decidido que voy a usar Ansible. Esta pieza de software se define como:

Ansible es categorizado como una herramienta de orquestación. Maneja nodos a través de SSH y no requiere ningún software remoto adicional (excepto Python 2.4 o posterior para instalarlo). Wikipedia

Para poder instalar Ansible es necesario disponer de Pip y Python en nuestro sistema. Yo lo decidí instalar en mi Raspberry Pi por lo que además tuve que instalar software adicional:

apt-get update
apt-get upgrade python
apt-get install libssl-dev libffi5-dev python-dev build-essential
cd /tmp/
wget wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py
pip install ansible

Dependiendo de la velocidad de la tarjeta SD de tu Raspberry Pi y la versión de ésta, puede tardar casi una hora en instalar todo el software necesario.

Una vez instalado el software, debemos crear el inventario de máquinas en /etc/ansible/hosts

mkdir /etc/ansible/
touch /etc/ansible/hosts

En mi caso voy a crear un grupo de servidores llamado servers que contiene un servidor vps y 2 raspberrys:

[servers]
mivps.example.com   ansible_connection=ssh  ansible_user=root
rpi1                ansible_connection=local #Host donde ejecuto ansible
rpi2                ansible_connection=ssh  ansible_user=pi    ansible_host=192.168.1.13

Donde la primera columna es el nombre del dispositivo al que nos vamos a conectar, ansible_host es la ip en el caso de que el nombre no se pueda resolver por dns y ansible_user es el usuario que usará ansible para conectarse al dispositivo.

Habitualmente, si no se especifica lo contrario, ansible intentará usar la clave ssh del usuario local para conectarse a los servidores remotos, si el usuario no tiene ninguna clave ssh generada, la crearemos.

mkdir $HOME/.ssh
chmod 600 $HOME/.ssh
ssh-keygen -t ecdsa -C "miusuario@miequipo"

Este proceso debe generar 2 claves (pública y privada) llamadas ~/.ssh/id_ecdsa.pub y ~/.ssh/id_ecdsa. Debemos copiar la clave pública (.pub) en el archivo authorized_keys del servidor remoto, para ello ejecutaremos el comando:

ssh-copy-id -i ~/.ssh/id_ecdsa root@mivps.example.com

Si queremos probar que se han copiado las claves ssh correctamente y tenemos acceso podemos ejecutar el comando

root@rpi1:~# ansible servers -m ping
mivps.example.com | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
rpi1 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
rpi2 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

Si todos los hosts aparecen como success, es que la instalación de claves ha ido correctamente.

Una vez copiadas todas las claves en los servidores, debemos crear el archivo /etc/ansible/update.yml:

---

- hosts: servers
  become: true
  become_user: root
  become_method: sudo
  tasks:
    - name: Update packages list [APT]
      apt: update_cache=yes
      when: ansible_os_family == 'Debian'
    - name: Upgrade packages [APT]
      apt: upgrade=safe
      when: ansible_os_family == 'Debian'
    - name: Upgrade packages [YUM]
      yum:
        name: '*'
        state: latest
        update_cache: yes
      when: ansible_os_family == 'RedHat'

Para finalizar, debemos lanzar el comando

root@rpi1:~# ansible-playbook /etc/ansible/update.yml

PLAY [servers] *********************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [mivps.example.com]
ok: [rpi2]
ok: [rpi1]

TASK [Update packages list] ********************************************************************************************************************************************************************************
changed: [mivps.example.com]
changed: [rpi2]
changed: [rpi1]

TASK [Upgrade packages] ************************************************************************************************************************************************************************************
changed: [mivps.example.com]
changed: [rpi1]
changed: [rpi2]

PLAY RECAP *************************************************************************************************************************************************************************************************
mivps.example.com          : ok=3    changed=2    unreachable=0    failed=0   
rpi1                       : ok=3    changed=2    unreachable=0    failed=0   
rpi2                       : ok=3    changed=2    unreachable=0    failed=0   

Si todos los hosts aparecen como 0 failed y 0 unreachable es que la ejecución del script ha ido correctamente.

Actualizar DNS con DHCP

En la entrada anterior vimos como montar un servidor bind y un server dhcp en linux para bloquear la resolución de algunas webs en nuestra red de área local. (Suplantando nuestros dns en la red local). Ya que tenemos el laboratorio montado en casa, podemos mejorar sus funcionalidades haciendo que todos los dispositivos que reciban una dirección DHCP de nuestro servidor queden registrados en el DNS con una entrada dinámica. Hacerlo a mano sería bastante laborioso y en breves tendríamos la zona dns desactualizada.

Para ello me he creado una zona a la que llamaré “canostra.local”, esta zona engloba mi red local. Siguiendo con el ejemplo anterior, tendremos 3 dispositivos en la red:

	192.168.22.1  --> Gateway
	192.168.22.2  --> Equipo Windows con reserva de DHCP
	192.168.22.11 --> DNS + DHCP.

Para poder crear el dynamic dns, el primer paso es editar el archivo para crear las nuevas zonas:

sudo vi /etc/bind/named.conf.local

Sigue leyendo

Let’s Encrypt la CA Open Source

Para todos aquellos que no conozcáis Let’s Encrypt os invito a que visitéis su Web . Esta entidad certificadora es Open Source y expide certificados gratuitamente siempre que podamos verificar la propiedad del sitio web mediante el protocolo ACME (automatic certificate management environment). Este protocolo nos permite administrar y expedir certificados de manera automática.

La única pega de esta entidad es que la validez de los certificados es de 90 días. Por lo que cada 3 meses hay que renovarlos en el servidor. Existen varios mecanismos de autenticación de un dominio, el más sencillo es la comprobación web donde la entidad certificadora nos solicita que creemos un .html con un contenido específico en nuestro dominio. Para automatizar el uso de ACME se creó un proyecto que se llama dehydrated en el que se gestionan en bash las llamadas a letsencrypt. Este proyecto es modular y permite parametrizar fácilmente las opciones de despliege de los certificados:

https://github.com/lukas2511/dehydrated

Este tipo de autenticación vía http presenta un problema, no puedes autenticar subdominios no publicados en Internet ya que la CA no podría conectarse a comprobar el challenge. Para este tipo de escenarios podemos utilizar la autenticación DNS01, donde se publica la información en un registro TXT del DNS que nos gestiona el dominio. Para usar este tipo de challenge, hay que especificar un “hook” a dehydrated para indicarle como tiene que interactuar con nuestro DNS.

En mi caso dispongo de una solución DNS de EfficientIP solid server, he creado un hook para usar dehydrated con SolidServer. Se puede encontrar en github:

https://github.com/berni69/solidserver-challenge

Para usarlo bastaría con descargarlo junto con dehydrated:

$ cd ~
$ git clone https://github.com/lukas2511/dehydrated
$ cd dehydrated
$ mkdir hooks
$ git clone https://github.com/berni69/solidserver-challenge.git hooks
$ chmod +x dehydrated
$ ./dehydrated --challenge dns-01  --cron --domain "test.example.com" --hook "hooks/solid-hook.py"

Saludos!

Tratando logs con awk

Hoy en el trabajo me he encontrado con una problemática bastante común cuando tratamos de filtrar logs: mucha información que no nos interesa.

Para solventar este problema, habitualmente, la primera aproximación sería con grep y cut pero habitualmente se quedan cortos ya que es complicado usarlos para filtrar por fecha/hora.

En este ejemplo se usará un archivo de log del estilo

2016/06/29 17:10:35.838:Fatal error core dumped
2016/06/29 17:15:35.838:Fatal error core dumped
2016/06/29 17:20:35.838:Fatal error core dumped
2016/06/29 17:30:35.838:Fatal error core dumped

Para poder filtrar por hora, podemos usar awk, en el siguiente script contaremos el numero de líneas que hay en un intervalo de tiempo determinado (por defecto, los últimos 15 min).

#!/bin/awk -f

BEGIN {

if(minutos==""){minutos=15 }
    umbral = minutos *60  # Miramos los ultimos N segundos del log 
    now = strftime("%H:%M:%S",systime())
    counter=0;
    debug=0
 }
{ 
    split($2,chunks,".");
    hour=chunks[1];
    m=split(hour,w,":")
    n=split(now,t,":")
    FIRSTTIME= (t[1]*3600) + (t[2]*60) + t[3]
    SECONDTIME= (w[1]*3600) + (w[2]*60) + w[3]
    DIFFTIME=(FIRSTTIME - SECONDTIME)
    if (debug == 1){
        printf("%s|%s|%s\n",FIRSTTIME,SECONDTIME,DIFFTIME)
    }
    if(DIFFTIME < umbral ){
        counter++;
    }
}
END { print  counter }

Para ejecutarlo bastaría con ejecutar:

cat mylog.log | awk -f script.awk -v minutos=8

Y el resultado sería

echo '2016/06/29 17:10:35.838:Fatal error core dumped
2016/06/29 17:15:35.838:Fatal error core dumped
2016/06/29 17:20:35.838:Fatal error core dumped
2016/06/29 17:30:35.838:Fatal error core dumped' | awk -f /var/www/scripts/countSuperacionesAma.awk -v minutos=8
1

Pues de este modo tan sencillo podemos tratar logs en función del tiempo.

Compilar un Kernel en Debian, Ubuntu y derivados.

IMG_0291-1.PNG
1. Conceptos básicos

Si posees conocimientos de GNU/Linux y sistemas operativos puedes aventurarte a la próxima sección; en la presente discutiremos conceptos básicos.

Cuando hablamos de “Linux” es frecuente referirnos al sistema operativo y sus aplicaciones y no al núcleo del sistema. La realidad es que Linux es solamente el núcleo del sistema (también denominado kernel): componente de gran envergadura que hace operar nuestra computadora. Entre las funciones más importantes del kernel: Sigue leyendo