martes, 20 de septiembre de 2011

Caché poisoning e inyección de javascript. Huella digital, Geolocalización y seguimiento a través de Google Analytics

El pasado 14 de Septiembre se presentaron en la Universidad Europea de Madrid los ultimos proyectos de Fin de Máster de Seguridad de la Información y las Telecomunicaciones.  En concreto yo, con mis compañeros presentamos el proyecto Japitracing sobre Geolocalización IP usando cache poisoning con inyección de javascript a través del servicio Google Analytics..
Portada de la memoria Fin de Master



Logo de la aplicación



En dicho proyecto se ha implementado la idea de hacer un envenamiento de la caché de los navegadores aprovechando la confianza que ofrece un servicio como Google Analytics. Este servicio se basa un un código javascript ( ga.js ) que es descargado desde la páginas que hacen uso de analytics y cuya función es recopilar información  variada del navegador y de aspectos de la navegación dentro de  la página para generar estadísticas que se envían al propietario de la  misma. Este script, es un objeto cacheable con una vida media de una o dos horas hasta que el navegador solicita actualización. Además está ampliamente extendido por internet, de modo que,  casi con total seguridad en una sesión de navegación normal se  visita una página que lo contiene. Esta situación se ha aprovechado para conseguir obtener información sobre una persona y su localización después de haber modificado el  script original ga.js de Gooogle Analytics y , tras una intervención en la comunicación, lograr inyectar en la caché del navegador de la "victima". La manipulación del ga.js ha sido de forma que al descargarse, se cachée con un tiempo largo de expiración para lograr  hacerlo "persistente" y que no sea de nuevo sustituido por el original una vez se deje de intervenir la comunicación (MiTM). El script modificado incluye un código que recogerá información sobre la IP ( y localización por tanto) , sobre el sistema operativo,  el navegador, sus plugins y su  historial. Una vez recopilada toda esa información será enviada, esquivado las restricciones de same origin policy  gracias a un  iFrame invisible que se crea en la carga de la página , a continuación, tras meter la información en un formulario se envía con POST hacia un servidor ajeno. Todo esto ocurre de forma transparente para el usuario cada vez que se visite una página con Analytics y el script ga.js (ya almacenado en caché) se invoque.

Una muestra de la información obtenida

En definitiva  un trabajo muy interesante, durante el cual hemos ido descubriendo las posibilidades que tiene javascript , la información del navegador ,su funcionamiento y caché para establecer un ataque que vulnere gravemente la privacidad del usuario. Todo ello incrementado aun más por las características particulares de las aplicaciones y configuraciones que cada usuario tiene y que conformarán lo que se da en llamar "huella digital". Para profundizar en este tema, las huellas digitales y la privacidad a la hora de navegar, que mejor que leer esta entrada en el blog de nuestro tutor en el proyecto.

Finalmente, agradecer públicamente el gran trabajo y la motivación de mis compañeros de máster asi como la ayuda de nuestros tutores en informática64, Pablo González y Chema Alonso.

jueves, 1 de septiembre de 2011

Cluster de alta disponibilidad + balanceo de carga


Hace un tiempo tuve que implementar un balanceo de carga con alta disponibilidad y me resultó una tarea interesante. Cuento un poco como lo hice.
Vamos a implementar un cluster de alta disponibilidad (ha) que mantenga un servicio de balanceo entre
dos servidores, en este caso y a modo de ejemplo dos servidores Web.
IP Virtual: 192.168.50.205
IP Nodo 1 ha: 192.168.50.215
IP Nodo 2 ha :192.168.50.225
IP servidor Web1: 192.168.50.211
IP servidor Web2: 192.168.50.221

Necesitaremos:

  • Alta disponibilidad : Heartbeat

Con este paquete se establece una comunicacion entre los miembros del cluster (nodos) y se
definen unos servicios que se quieran poner en alta disponibilidad. Uno de los nodos será el master y
será quien dé el servicio. Si se cae, el/los otros nodos tomarán el servicio hasta que se recupere.
Nosotros vamos a poner como servicio el ldirectord que es el que se encarga de balancear la carga
sobre los servidores Web.

  • Balanceo LVS: Ldirectord

Es el paquete que propiamente proporciona el balanceo de carga. Se configura definiendo una
IP Virtual que el servicio se encarga de mantener a la “escucha” y repartir las demandas sobre los
servidores reales (web).


  • IP_Forwarding:

Como el balanceador tiene que hacer forwarding de las peticiones sobre la IP virtual a las reales, es
requisito habilitar en el kernel esta característica:
# /etc/sysctl.conf
net.ipv4.ip_forward = 1

Instalación :

apt-get install heartbeat ldirectord (debian)
yum heartbeat ldirectord install (RedHat)

Configuración:

Ldirectord
Lo primero y como queremos que este servicio sea controlado por heartbeat y que sea éste quien lo
arranque, lo deshabilitamos del boot de la máquina:

update_rc.d ldirectord remove (debian)
chkconfig ldirectord off (RedHat)


Creamos el fichero de configuración : ldirectord.cf y lo ubicamos en /etc/ha.d/conf
En este caso va a tener la pinta:

(No entro a describir todos los parámetros puesto que es extensísmo, consultar man)


# vim /etc/ha.d/ldirectord.cf
checktimeout=10
checkinterval=2
autoreload=no
logfile="/var/log/ldirectord.log"
quiescent=yes
virtual=192.168.50.205:80
real=192.168.50.211:80 gate
real=192.168.50.221:80 gate
fallback=127.0.0.1:80 gate
#protocolo que se gestionará
service=http
#Scheduler es el algoritmo usado para hacer el reparto de carga rr=RoundRObin, lc= least
conections... etc (ver man ldirectrd)
scheduler=rr
protocol=tcp
#Checktype es la “prueba de vida” que hará el ldirectord para saber si el servidor real esta vivo, en
este caso negotiate que comprobará una respuesta (hay otros por ej connection..)
checktype=negotiate
#archivo que se solicitará en los servidores web para la prueba de vida, debe estar en DocumentRoot
request="test/ldirector.html"
#El archivo debe contener unicamente esta linea de texto para confirmar la validez del sitio
web
receive="Si, estoy vivo!"


Con esto el ldirectord creará una IP virtual 192.168.50.205:80 que repartirá a los servidores reales por
el método Direct Routing (gate). Existen 3 métodos: NAT ,Direct Routing e IP Tunneling.

  • NAT:

 Las peticiones entrantes llegan a la IP virtual y son reenviadas hacia los servidores reales
   cambiando la IP destino (NATeo). La respuesta de los servidores reales vuelve al balanceador
  quien de nuevo cambia la IP y reenviía al petcionario. Como todo el tráfico pasa por el
   balanceador suponde normalmente un cuello de botella para el cluster.

  •  IP Tunneling

   LVS manda las peticiones a los servidores reales a través de un tunel IP y los servidores
   responde directamente al peticionario a través de sus tablas de enrutamiento (necesitan pues de
   gateway).

  •   Direct routing

 Los paquetes del peticionario son enviados directamente a los servidores reales (forwarding).
Como el paquete IP no es modificado los servidores reales para aceptarlo necesitan una interfaz
virtual no-ARP ( para evitar conflictos de red al tener la misma IP que la virtual). La respuesta
se envía directamente al peticionario desde el servidor real.

Lo que hace Ldirectord:
Conecta cada 10 segundos (checkinterval) con cada servidor real y pide la prueba
192.168.50.205:80/test/ldirector.html (request/receive). Si no recibe la cadena que pusimos en ese
fichero (“Si, estoy vivo”) en un tiempo de 2 segundos (checktimeout), eliminara ese servidor del “pool”
de servidores disponilbles a los que mandar peticiones. Estará de nuevo disponible cuando el test sea
exitoso.
Copiamos este fichero de configuracion ldirectord.cf en /etc/ha.d/conf del resto de nodos
Una vez definido el servicio de balanceo, vamos a ponerlo en Alta Disponibilidad a través de
HeartBeat.

Hearbeat


Para establecer la comunicación entre los nodos hay que definir un método de autenticación que se
hace a través del ficherito /etc/ha.d/authkeys
#vim /etc/ha.d/authkeys
auth 1
1 md5 EstaEsmiClaveSecreta
Este fichero que contiene la clave de autenticacion y el método de encriptación (md5) lo protegemos
para que solo lo lea root:
#chmod 600 /etc/ha.d/authkeys


Otra cosa a tener en cuenta es que los nodos se “conozcan”, es decir editar /etc/hosts en ambos y poner
los nombres de los nodos del cluster. Poner el nombre que devuelva el comando : uname -n

# vi /etc/hosts
192.168.50.215 Nodo1 NODO1
192.168.50.225 Nodo2 NODO2


Definimos el cluster: /etc/ha.d/ha.cf (bastante simplificado)


#Fichero de log
logfile /var/log/ha-log
logfacility local0
keepalive 2
deadtime 30
initdead 120
# Tarjeta por la que se realizará el broadcast
bcast eth0
udpport 694
auto_failback on
#nombre de host (uname -n) de los equipos directores
node Nodo01
node Nodo02
Copiamos este fichero en /etc/ha.d/ del resto de nodos.
Nota: La definicion del cluster se puede simplificar bastante con la herramienta gráfica hb_gui
Por último ya solo queda definir los servicios en alta disponiblidad que en nuestro ejemplo será el
ldirectord.
Los recursos se definiran en /etc/ha/haresources

El formato viene bien descrito en los comentarios del propio fichero. En este ejemplo va a tener la
pinta:


#vi /etc/ha.d/haresources
Nodo01 IPaddr2::192.168.50.205/24/eth0/192.168.50.255 ldirectord::ldirectord.cf
LVSSyncDaemonSwap::master


El ficherito haresources será identico en todos los nodos del cluster. La referencia al nombre del nodo
es el nodo que será el preferido para actuar como master (en este caso el Nodo1).
El formato que vemos es:

Nodopreferido IP_para_el recurso1 recurso:parametro1.......
En el formato de la IP se ha especificado IP/mascara/interfaz/broadcast.
El recurso LVSSyncDaemonSwap es el demonio que habilita las capacidades de la alta disponibilidad.
Sincronización en te los nodos, commutación...

Configuración de los servidores reales


Debemos configurar los servidores reales de modo que acepten el forwarding que les envía el
balanceador LVS por la IP virtual.
Tenemos que configurar un alias virtual que levante la direccion virtual y además hacer que sea “sorda”
a ARP de modo que no desvele la IP y no entre en conflicto.
Los cambios a realizar en los parámetros del kernel de los sevidores reales serán:

# /etc/sysctl.conf
#habilitar la opcion de ignorar ARP
net.ipv4.conf.all.ARP_ignore = 1
#No responder a las solicitudes de ARP si la direccion IP esta configurada sobre el interfaz
“lo” (loopback) o cualquier otro interfaz virtual eth0:0
net.ipv4.conf.eth0.ARP_ignore = 1
#Habilitar la opcion de anuncio ARP
net.ipv4.conf.all.ARP_announce = 2

Como la fuente IP de la peticon ARP entrará en la cache ARP del destino esto tiene el efecto de
anunciar esta direccion. Esto no es deseable para “lo” o cualquier otro interfaz virtual ethx:0 de los
servidores reales. Usando este valor haremos que los servidores reales siempre que reciban una peticion
ARP usen la IP real como fuente de la peticion ARP.

net.ipv4.conf.eth0.ARP_announce = 2

Y cargamos los cambios con:

# sysctl -p


Una vez hechos estos cambios ya tendremos la posibilidad de levantar el interfaz virtual que nos sirva
la IP virtual sin conflictos.
Definimos en los servidores reales sobre lo, la interfaz virtual lo:0 añadiendo:


# /etc/network/interfaces
...
iface lo inet loopback
auto lo:0
iface lo:0 inet static
address 192.168.50.205
netmask 255.255.255.255
Esta interfaz será la encargada de recibir el forwarding del balanceador.

Gateway:
Hay que tener en cuenta que la respuesta de los servidores reales será directa a los usuarios con lo cual
estos deben tener el router en el default gateway.
Con esto ya queda acabada la configuración.
Finalmente, ya solo queda arrancar el cluster ejecutando en todos los nodos del cluster :

# service hearbeat start
.... Y a depurar, claro.