Posts Tagged ‘how-to’

DomainKeys Identified Mail

Thursday, October 23rd, 2008

DomainKeys Identified Mail, o DKIM, es un sistema de autenticación que permite verificar que el correo realmente proviene de quien dice provenir. Como los spammers suelen falsificar los remitentes de los correos que mandan, también veremos como esa verificación nos puede servir como un método más para luchar contra el correo no deseado.

DKIM recuerda bastante al Sender Policy Framework, o SPF, cuya finalidad es que los servidores puedan verificar que el servidor que les está entregando un correo está autorizado a hacerlo. Es decir, si el servidor mx.example.org está intentando entregar un correo con remitente user@example.com a mi servidor, este usará SPF para verificar si mx.example.org está autorizado a gestionar el correo de ese dominio. La idea es buena pero, por la forma en que se hace, tiene problemas cuando hay redirecciones o forwards. Para más información, podéis leer la introducción a SPF del proyecto OpenSPF o el artículo de la Wikipedia [en inglés].

Quería introducir un poco SPF para poder compararlo con DKIM ya que ambos tienen finalidades similares y usan el sistema de DNS para publicar la información necesaria. Pero así como SPF publica en DNS qué servidores pueden o no enviar correo de un dominio, DKIM publica una clave pública que se usará para verificar que el correo se originó desde un servidor legítimo, evitando el problema de los forwards. Pero nos estamos avanzando un poco…

¿Cómo funciona?

Simplificando bastante: a la hora de enviar, el remitente firma el mensaje y añade esa firma al correo. Entonces, cualquiera de los servidores por los que pasa el correo, puede comprobar su autenticidad verificando la firma. Aunque cualquiera de los servidores puede, la comprobación normalmente se realiza en el servidor destinatario.

Profundizando algo más, DKIM se basa en sistemas muy usados y conocidos como son la criptografía asimétrica, las funciones de hash y, como ya habíamos anticipado, DNS. Para entender mejor su funcionamiento, vemos la infraestructura que hay que configurar para que pueda funcionar:

  1. El administrador del dominio de correo debe generar un par de claves asímetricas.
  2. Seguidamente, configurará la clave privada en sus servidores de correo, que la usaran para firmar los mensajes.
  3. Finalmente, publica la clave pública como un registro TXT en la zona DNS de su dominio para que los servidores que quieran comprobar la autenticidad de los correos puedan obtenerla.

Ahora ya podemos ver el proceso con más detalle: el servidor remitente calcula el hash del correo teniendo en cuenta el cuerpo y algunas cabeceras, y cifra ese hash con la clave privada generando la firma que se añade al correo. Cuando un servidor quiera verificarlo, como necesitará la clave pública para hacerlo, consultará al sistema DNS para obtenerla y poder realizar la comprobación. Si el correo se originara desde un servidor ilegítimo, como no tendría la clave privada adecuada, la comprobación de la firma fallaría poniendo en evidencia al servidor como posible spammer o phisher.

Como la comprobación no se basa en quién nos está entregando el mensaje sino en quién lo originó, este esquema no sufre de los problemas de SPF con los forwards. Sin embargo, al estar basado en firma digital, tiene problemas con las modificaciones que pueda sufrir el correo durante su transmisión. Por ejemplo, si se añade un disclaimer después de que se haya firmado, la verificación fallará.

Para más información sobre DKIM os remito su web, donde encontrareis multitud de documentación, y, como nó, a la Wikipedia.

Como referencias, decir que tanto Yahoo! como Gmail son dos grandes ejemplos de ISPs que usan DKIM en sus servidores.

DKIM en SpamAssassin

Finalmente, veamos como podemos configurar SpamAssassin para sacar provecho de este sistema. Estoy dando por supuesto que usamos Debian Etch y que ya tenéis el MTA (Postfix o similar) y el SpamAssassin instalados y configurados. Sólo mostraré la configuración a realizar para que se empiecen a comprobar las firmas de DKIM. Desgraciadamente, la versión que viene con Etch no es del todo adecuada por lo que deberemos añadir el repositorio de backports a nuestro source.list. Una vez añadido, actualizaremos la lista de paquetes e instalaremos libmail-dkim-perl, con todas sus dependencias, desde backports:

  server:~# aptitude update
  server:~# aptitude -t etch-backports install libmail-dkim-perl

Ahora sólo falta habilitar el plugin Mail::SpamAssassin::Plugin::DKIM descomentando la correspondiente línea en el fichero /etc/spamassassin/v312.pre. Recordad reiniciar spamd, amavisd-new o el content-filter que uséis para que se aplique la nueva configuración.

Como ejemplo, veamos las cabeceras de un correo enviado desde gmail:

X-Spam-Status: No, score=-0.124 required=4.5 tests=[AWL=-0.185,
	BAYES_20=-0.74, DKIM_SIGNED=0.001, DKIM_VERIFIED=-0.001,
	DNS_FROM_SECURITYSAGE=0.001, HTML_MESSAGE=0.001, P0F_Unknown=0.8,
	SPF_PASS=-0.001]
...
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:message-id:date:from:to
         :subject:mime-version:content-type;
        bh=JvMz4j1uNftb2YwcCYFAjZF73T5HtaC0paeyk3KqFao=;
        b=s2/id2fqmQMef9gWIvn6jhs09lz9nnyOrwepQtQQdzd6Bj8iB/7b2G3PN+bLcOW0k1
         kTs7ew+y8P1rROBlA+T8CpsYirWL0gSp6YZidyhN2SHJVg9ZXQ7oWq6czAcqs/y3871n
         l4Wnm53EqPPNn4Tqos6ruDghAfyJ/deBxFY3Q=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=message-id:date:from:to:subject:mime-version:content-type;
        b=U6s9wCp2Q5U7DC0WcQGJ6S6hNwTNmPUiklMd0RtMgB+pJzvP8T/NaqT43Q4QyaukPz
         ig4b3S0/QF3B6uOctVvYQE9YAlgbilx+QxthVzhtc9xvyfePgF63RoebvK28hNlL5VUn
         +0cdEBbEOqkPzo1d1j5XaDGDUV6W/0xHRZb2o=
Received: by 10.210.65.2 with SMTP id n2mr4808273eba.65.1224441206376;
        Sun, 19 Oct 2008 11:33:26 -0700 (PDT)
Received: by 10.210.113.2 with HTTP; Sun, 19 Oct 2008 11:33:26 -0700 (PDT)
Message-ID: <57e22bd310j416695a2d215d0810191133h6297c2b8a@mail.gmail.com>
Date: Sun, 19 Oct 2008 20:33:26 +0200
From: "Gmail user" <user@gmail.com>
To: user@example.com
Subject: DKIM test
MIME-Version: 1.0
Content-Type: multipart/alternative;

Como podéis ver, con la puntuación que le dá SpamAssassin por defecto no mejoramos la discriminación de spam: +0.001 por venir firmado que se compensa con -0.001 porque la firma es correcta. En la lista de correo de spamassassin-users podemos encontrar algunas sugerencias (y sus actualizaciones).

Conclusiones

DomainKeys Identified Mail es otro sistema pensado para verificar el origen del correo que, como el resto de alternativas, tiene sus ventajas e inconvenientes. Y hemos dado unas pinceladas sobre como se puede usar para ayudar a nuestro sistema anti-spam. En un futuro post, explicaré como configurar nuestro Postfix y Bind para que nuestro correo use DKIM.

Yo, personalmente, pienso que más que intentar parchear el protocolo SMTP, debería tomarse la decisión de hacer “borron y cuenta nueva” y diseñar un nuevo protocolo de transmisión de correo teniendo en cuenta todo lo aprendido hasta ahora y especialmente pensado para no permitir el spam.

Protegiendo el correo con Fail2Ban

Tuesday, October 21st, 2008

Recientemente expliqué como Fail2Ban podía ayudarnos a ponérselo más difícil a esos script-kidies que se dedican a intentar entrar por SSH en nuestras máquinas realizando ataques de fuerza bruta.Hoy vamos a ver como usar esa misma herramienta para proteger de esos ataques a los servicios de correo. La configuración que voy a explicar supone que estamos usando Postfix como MTA, Cyrus como servidor POP3 e IMAP y SASL para autenticar a los usuarios.

Servidor SMTP

Como ya he comentado, lo que queremos es proteger el MTA de ataques de fuerza bruta: si alguien consiguiera averiguar unas credenciales correctas podría usar nuestro servidor para hacer relay. Dentro del paquete de fail2ban en Debian tenemos casí toda la configuración que nos hace falta. De hecho, se define el filtro sasl, pero la expresión regular no es del todo correcta. Para solucionarlo, crearemos el fichero /etc/fail2ban/filter.d/sasl.local (tal y como se recomienda en /usr/share/doc/fail2ban/README.Debian.gz<(code>) con el siguiente contenido.

[Definition]
failregex = : warning: .*+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed

Es la misma línea que en sasl.conf pero con ligeras modificaciones, como la eliminación de la marca de final de línea ($) en la expresión regular.

Activaremos la regla sasl modificando/creando el fichero /etc/fail2ban/jail.local:

[sasl]
enabled  = true

Para que se aplique la nueva regla, debemos recargar la configuración:

 server:~# fail2ban-client reload
 <pueden salir unos warnings>

 server:~# fail2ban-client status
 Status
 |- Number of jail:      2
 `- Jail list:           sasl, ssh

Si alguno de los comandos da un error de “Could not find server“, es que el servidor de fail2ban no está arrancado.

Servidores POP3 e IMAP

Por coherencia, si protegemos el servidor SMTP debemos hacer lo propio con los servidores de POP3 e IMAP. Si no, como los tres servicios comparten la base de datos de usuarios, podrían usar uno de los servicios desprotegidos para averiguar la contraseña por fuerza bruta. Como los mensajes de error de autenticación no indican el servicio que ha usado el usuario para conectarse, vamos a tratar los servidores POP3 e IMAP en conjunto. Esto es, al detectarse errores de autanticación se bloquearan todos los servicios.

Para realizar esta configuración, empezaremos creando el filtro en /etc/fail2ban/filter.d/cyrus.local con el siguiente contenido:

[Definition]
failregex = : badlogin: .*\[<HOST>\] (?:plaintext|LOGIN|(?:CRAM|DIGEST)-MD5|NTLM) .*SASL\(-13\): authentication failure
ignoreregex =

Y acabamos añadiendo las reglas necesarias al final del fichero /etc/fail2ban/jail.local:

[pop3]
enabled  = true
port     = pop3
filter   = cyrus
logpath  = /var/log/mail.log

[pop3s]
enabled  = true
port     = pop3s
filter   = cyrus
logpath  = /var/log/mail.log

[imap2]
enabled  = true
port     = imap2
filter   = cyrus
logpath  = /var/log/mail.log

[imaps]
enabled  = true
port     = imaps
filter   = cyrus
logpath  = /var/log/mail.log

Debemos definir una regla por puerto porque la versión 0.7.5 de fail2ban (la que tenemos en Etch) no soporta que se indique más de un puerto por regla. Versiones más recientes, como la versión 0.8, parece que si lo soportan (Si alguien lo comprueba, que me lo comente.  Gracias).

Como siempre, recargad la configuración y comprobad que se estén usando las reglas recién definidas.

Conclusiones

Fail2Ban es una gran medida disuasoria y con estas configuraciones conseguimos frenar en gran medida los ataques de fuerza bruta contra los servicios autenticados de correo: con la configuración por defecto, el servidor no aceptará conexiones de ese cliente durante diez minutos tras tres intentos fallidos.

Aunque la seguridad es necesaria, suele ser incómoda. Pensad en el usuario que intenta configurar su Outlook Expres en casa pero se le ha olvidado la contraseña (como si la hubiera recordado durante más de diez segundos… cuanto daño ha hecho la opción “Recordar contraseña”…) y tras varios intentos os llama. Como el servidor le ha bloqueado el acceso por un tiempo, aunque le podáis dar la contraseña correcta, deberá esperar. Dependiendo de como sean vuestros usuarios, es posible que debáis jugar un poco con los parámetros bantime y maxretry.

Como véis, no resulta muy complicado dotar de algo más de seguridad a nuestros servidores si conocemos las herramientas adecuadas y como usarlas.

One time passwords con OPIE

Tuesday, October 14th, 2008

Continuando con mis posts sobre seguridad, tema que me apasiona, hoy voy a explicar como implantar un sistema de One-Time-Password en nuestros servidores Linux.

Como se puede sobreentender de su nombre, los sistemas de One-Time-Password son sistemas de autenticación en los que cada contraseña se utiliza una única vez. Esto nos puede resultar útil en el caso de que debamos hacer login en situaciones comprometidas: usando un protocolo con el que las credenciales viajan en claro (sin cifrar) por la red, desde un equipo del que no podemos asegurar su integridad (que no tenga keyloggers instalados, por ejemplo), etc.

Aunque existen tres formas de implementar sistemas OTP, desde un punto de vista práctico existen dos tipos:

  • Basados en secuencia: cada vez que usamos una contraseña esta deja de ser válida y el sistema nos pedirá la siguiente en el proximo login. Mientras no hagamos login, el sistema nos seguirá pidiendo la misma.
  • Basados en relojes sincronizados: la contraseña va cambiando con el tiempo, se use o no. El principal requisito de estos sistemas es que el servidor y el generador de la contraseña deben estar sincronizados en el tiempo.

El sistema que os presento es OPIE, que está basado en secuencia, es una implementación de S/Key. Si elegí este fué por sencillez de implementación ya que todo el software necesario esta disponible desde los repositorios oficiales de Debian. Pero le he encontrado dos “problemas”: la página del proyecto no funciona (al menos mientras estoy escribiendo este post) y que no hay desarrollos nuevos desde 1998.

(more…)

Fail2ban

Saturday, October 11th, 2008

Una de las principales preocupaciones de cualquier administrador de sistemas es la seguridad de sus servidores, y más particularmente de las intrusiones. La principal medida que se suele usar para evitarlas es el uso de Firewalls, pero siempre debemos dejar abiertos los puertos por los que da servicio (un servidor al que no nos pudiéramos conectar no es muy útil :-P ), y si esos servicios son autenticados, pueden ser sujetos de ataques de fuerza bruta para averiguar contraseñas. Uno de los principales servicios que sufren este tipo de ataques es el de SSH y para protegerlo disponemos de fail2ban.

Fail2ban es un servicio que vigila una serie de ficheros de log y cuando detecta intentos fallidos bloquea la dirección IPdesde la que se han realizado añadiendo una regla de iptables.

Para instalarlo, en Debian basta con un "aptitude install fail2ban". La configuración por defecto trae activada la protección de SSH y a parte de bloquear la IP infractora envía un correo a root. A parte de la protección de SSH, trae configuraciones para apache, postfix, qmail, vsftpd, etc. y soporte para otros sistemas de firewall a parte de iptables.

Fail2ban no nos asegura una protección total, es sólo una medida más para ponérselo más difícil a los que intentan entrar de forma no autorizada en nuestro servidor, principalmente contra script-kiddies.

O.S. fingerprinting como medida antispam

Friday, October 3rd, 2008

Hay ocasiones en que el tema del spam me recuerda a una escalada armamentística, en la que las dos partes de un conflicto van evolucionando sus medios y técnicas para obtener ventaja sobre el otro. Un ejemplo de esta escalada en el campo del spam son los filtros bayesianos: hace ya un tiempo los sistemas antispam implementaron filtros bayesianos [Wikipedia], que básicamente son unos algoritmos que son capaces de “leer” los correos y puntuar cuan probable es que ese correo sea spam. Algunos spammers reaccionaron enviando los correos con una imagen en la que incluían el texto de manera que los filtros bayesianos no pudieran leerlo. Para combatir esta técnica, los sistemas antispam implementaron sistemas de reconocimiento de carácteres (OCR) para poder “leer” el texto contenido en las imágenes, a lo que los spammers reaccionaron modificando el fondo de las imágenes para hacer más difícil el reconocimiento. Etc.

En este post os voy a explicar una técnica para luchar contra el spam que he descubierto recientemente y como configurarlo.

Introducción

Esta técnica antispam sólo es útil si se implementa a nivel de servidor de correo, y se fundamenta en dos pilares:

  1. Como se puede suponer del título del post, uno de los pilares es la detección de la versión del sistema operativo del servidor remoto que está intentando entregar un correo a una de las direcciones que alojamos.
  2. El otro pilar es el hecho de que nadie en su sano juicio instalaría un servidor de correo sobre un Windows XP, ya que está destinado a estaciones de trabajo y no a servidores. Pero incluso así, la gran mayoría de spam proviene de Windows XP, que seguramente tendrán instalado un virus que los convierte en relayers.

Es decir, si somos capaces de determinar que correos entrantes nos los está enviando un Windows XP, lo podremos usar para diferenciar mejor el correo legítimo del spam.

(more…)

Portal captivo muy simple

Sunday, September 21st, 2008

Introducción

Recientemente se me ocurrió la idea de si sería posible que si un equipo no registrado se conectara a una red privada (un consultor que llega a una empresa, por ejemplo) se le presentara una página web indicando que debe ponerse en contacto con el soporte técnico para que le den acceso. Vaya, una especie de portal captivo pero mucho más simple.

Después de darle unas pocas vueltas llegué a una posible solución, que es la que voy a exponer a continuación. Mi intención no es dar una configuración detallada al 100%, básicamente porque no dispongo de un entorno donde poderlo probar todo. Lo que quiero es dar las ideas y poner parte de las configuraciones necesarias para conseguirlo.

La idea es la siguiente:

  1. Tenemos el DHCP configurado de tal manera que a los equipos de la red se les asigna siempre la misma dirección IP de un determinado rango a partir de su dirección MAC. A las MACs no registradas les asignamos una dirección IP de un pool formado por direcciones de una rango totalmente diferente al de la red que se le asigna a las MACs conocidas y que no está enrutada (por tanto no tiene salida fuera de la red local). El pool “captivo” estará configurado para que el servidor DNS que se asignará a esos dispositivos sea uno que estará en el mismo segmento de red y dentro de la misma red IP que las direcciones (recordad que la red del pool no esta enrutada).
  2. Configuraremos el servidor DNS que usaran esos equipos no registrados de manera que resuelva todos los nombres de dominio con una misma dirección IP, la de un servidor local que también estará dentro de la misma red IP que el pool (que es la única red que pueden ver).
  3. Y el servidor Web siempre devolverá la misma página independientemente de la URL que se le solicite. En esa página se le indicará al usuario que el equipo desde el que está accediendo no esta autorizado, que se ha registrado su acceso y que se ponga en contacto con el soporte técnico para que le den acceso.

Por ejemplo, supongamos que en nuestra red usamos las direcciones 192.168.0.0/24, que el DNS “bueno” está en la dirección 192.168.0.1 y el default gateway también es el 192.168.0.1. Para las MACs no registradas, el pool tendrá direcciones de la red 172.16.0.0/24, de la 172.16.0.16 a la 172.16.0.254, el servidor DNS para los equipos no registrados será la 172.16.0.1 y el servidor web estará en la misma máquina.

De esta forma, cuando alguien enchufe un PC a la red y no lo haya notificado previamente, cuando intente acceder a alguna web le saldrá la página que le indicará que debe registrar su equipo.

Configuración

Vamos a ver como debemos configurar los diferentes servicios que intervienen para implementar esta funcionalidad.

DHCP

La configuración del servidor de DHCP no tiene mucho misterio. Básicamente es traducir los requisitos a nivel de DHCP a configuración. Pego la parte relevante de la configuración.

/etc/dhcp.conf

shared-network LAN {
  subnet 172.16.0.0 netmask 255.255.255.0 {
    allow unknown-clients;
    option routers 172.16.0.1;
    option domain-name-servers 172.16.0.1;
    range   172.16.0.16 172.16.0.254;
    max-lease-time 30;
    default-lease-time 30;
  }

  subnet 192.168.0.0 netmask 255.255.255.0 {
    option routers 192.168.0.1;
    option domain-name-servers 192.168.0.1;
    option subnet-mask 255.255.255.0;
    max-lease-time 86400;
    default-lease-time 86400;
  }
}

# Equipos registrados
group {
  host PC1 {
    hardware ethernet 00:01:02:e7:ef:15;
    fixed-address 192.168.17;
  }

  host PC2 {
    hardware ethernet 00:00:21:cb:22:fa;
    fixed-address 192.168.18;
  }
}

Bind

Como servidor DNS usaremos el Bind y tal y como he comentado anteriormente, debemos configurarlo de manera que resuelva cualquier nombre de dominio que le solicitemos con la dirección IP del servidor en el que configuraremos el Apache. Por suerte, Bind tiene soporte de wildcards.

Importante: poner el TTL de esas resoluciones muy bajo, varios segundos a lo sumo. Si no, tras registrar el PC, seguiría sin ver las páginas a las que hubiera intentado acceder mientras tenÍa configurado el DNS del portal captivo ya que la cache de DNS de su S.O. seguiría “resolviendo” el nombre de dominio como la IP de la web del portal captivo.

/etc/bind/named.conf

options {
  directory "/var/cache/bind";
  listen-on { 172.16.0.1; };
  version "Captive Portal DNS Server";
  recursion no;
};

zone "." {
  type master;
  file "/etc/bind/db.captive";
};

/etc/bind/db.captive

$TTL    1
@       IN      SOA     captive.local. netmaster.local. (
                        0000001         ; Serial
                        604800         ; Refresh
                        86400         ; Retry
                        2419200         ; Expire
                        1 )       ; Negative Cache TTL
;
@       IN      NS      captive.local.
*.      IN      A       172.16.0.1

Apache

Partiremos de una instalación estándar de Apache2 de Debian y configuraremos el host virtual por defecto de manera que la web tendrá simplemente una página HTML y como mucho unas cuantas imágenes (por ejemplo, el logo de la empresa). También configuraremos unas reglas de rewrite para que pidan la URL que pidan salga la misma página.

Importante: para evitar problemas con las caches de los navegadores, la página debería tener una cabecera de Cache-Control forzando que el navegador siempre se la descargue en cada consulta.

/etc/apache2/sites-available

<Directory /var/www/>
  Options Indexes FollowSymLinks MultiViews
  AllowOverride FileInfo
  Order allow,deny
  allow from all
</Directory>

Pondremos el index.html que queramos mostrar en /var/www/index.html y crearemos el fichero .htaccess con las reglas de reescritura y de no-cache:

/var/www/.htaccess

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

<IfModule mod_headers.c>
  Header set Cache-Control "no-cache"
</IfModule>

No debemos olvidarnos de habilitar los modulos de rewrite y header:

a2enmod rewrite
a2enmod headers

Y con esto ya tendríamos nuestro portal captivo.

Mejoras

Si no quisiéramos/pudiéramos tener un servidor dedicado al portal captivo, podríamos poner la configuración necesaria de DNS en una vista y configurar el Bind para que las IPs del rango captivo fueran a esa vista en particular, y a nivel de Apache podríamos usar un Virtual Host basado en dirección IP. Si alguien no supiera como hacerlo, le debería ser bastante fácil encontrar documentación en Internet sobre somo hacerlo.

Si lo que nos interesa es que los equipos no registrados no tengan ningún tipo de conectividad, escenario mucho más seguro, deberemos pensar en una solución basada en 802.1x. Pero para ello, tanto la electrónica de red como los equipos deben soportar ese protocolo.