Contribución de Ángel Alonso-Párrizas:
Esta serie de posts sobre Android son el resultado de un trabajo hecho como parte del proyecto final del Máster en seguridad y análisis forense en la Universidad de Dublin City University. El trabajo original con título "Securely deploying Android devices¨ se puede encontrar en inglés aquí, así como la publicación del paper en la web del SANS Institute. Como nada del proyecto ha sido publicado en castellano aprovecho el blog del colega José Selvi, al cual tengo el placer de conocer desde nuestros años mozos en la Universidad, para exponer el trabajo en la lengua de Cervantes :)
Antes que nada comentar que la idea de este proyecto surgió cuando trabaja en una compañía en la que necesitábamos dar cobertura al uso de Android de manera segura en entornos corporativos. Así que algunas de las funcionalidades que son limitadas en este proyecto pueden no tener tanto sentido si se trata de un usuario final (como por ejemplo la posibilidad de instalar software). Teniendo esto en cuenta, vamos al lío.
Android está sujeto a los mismos problemas de seguridad que cualquier sistema operativo moderno con la particularidad de que el acceso a Internet es itinerante, es decir, puede usarse cualquier conexión WiFi o 3G de manera dinámica. Esto implica ciertos riesgos, como por ejemplo ataques de tipo sniffing. Además, el modelo de distribución de software vía los distintos repositorios (como Market) lo hacen muy vulnerable al malware. Estos son los puntos más débiles de Android pero no los únicos.
Si entrar mucho al detalle, el modelo de seguridad de Android a nivel de Sistema Operativo es robusto ya que las aplicaciones se ejecutan en la máquina virtual (Dalvik) de manera aislada (como en un sistema operativo tradicional donde cada proceso tiene su espacio de memoria). Además, el sistema de ficheros sigue el modelo de permisos de Linux. La diferencia fundamental radica en que en lugar de múltiples usuarios tenemos múltiples aplicaciones (cada aplicación tiene asignado un UID).
Con este modelo es posible definir con cierta granularidad, cuando se desarrolla la aplicación, que permisos necesita ésta para ejecutarse (esto se hace en un fichero llamado AndroidManifest.xml), pero es el usuario final quién tiene la última palabra al aceptar (o no) los permisos. Los problemas que subyacen de este modelo son dos: que un desarrollador con malas intenciones cree un fichero AndroidManifest.xml con más permisos de los necesarios y que un usuario acepte los permisos de una aplicación con más permisos de los requeridos. Si hablamos de un entorno corporativo, donde las políticas de seguridad deben restringir la instalación de cualquier software, aún hay más motivo para mitigar estos riesgos.
Teniendo en cuenta los problemas expuestos de manera resumida arriba, los objetivos principales de este trabajo se pueden resumir en lo siguientes puntos:
- Implementar un canal de comunicación seguro a través de VPN (OpenVPN) y enrutar todo el tráfico a través del túnel. Implementar políticas de filtrado de tráfico entrante y saliente.
- Limitar el acceso a la administración del dispositivo y centralizar su acceso. El acceso al dispositivo sólo debe ser permitido a los administradores de seguridad a través de SSH con claves.
- Deshabilitar la instalación del software. Solo debe instalarse software autorizado por las políticas de seguridad corporativas y el usuario no debe poder instalar nada.
- Implementar una política de contraseñas alineados con los estándares de la compañía. El dispositivo debe de borrarse después de un número determinado de fallos en la contraseña.
- Habilitar funcionalidades remotas de seguridad, como por ejemplo el borrado remoto, la localización a través de GPS (Google Maps) o el borrado mediante mensaje de texto.
- Incluir capas adicionales de seguridad como el antivirus.
- Deshabilitar servicios y dispositivos inseguros o innecesarios, como por ejemplo el bluetooth o la tarjeta SD.
Las herramientas que son necesarias para este proyecto son:
- Un smartphone al que se le pueda instalar la versión de ROM Cyaongenmod (en el caso de este proyecto fue un HTC Desire).
- Un servidor con Linux (para este proyecto use un VPS ubicado en Holanda).
- El kit de desarrollo SDK para Android (indistintamente en Linux, Mac o Windows).
- Tarjeta 3G y un punto de acceso WiFi.
- Algunas herramientas como OpenVPN, Iptables y SSH.
Cifrar el canal de comunicación e implementar políticas de filtrado
La idea fundamental de este punto consiste en enviar todo el tráfico a través de un túnel VPN-SSL independientemente de que nos conectemos por 3G o WiFi. Para ello, lógicamente, lo primero es establecer el túnel entre el dispositivo y el VPN endpoint (que es el VPS bajo nuestro control o un sistema Linux).
Además, implementaremos políticas de firewall en Android mediante iptables, de tal manera que el único tráfico permitido es el necesario para establecer el túnel y para enrutar todo el tráfico hacia el VPS. Se puede ver un diagrama con la arquitectura en la siguiente figura:
Como muestra la figura, todo el tráfico pasa por el VPN endpoint, por lo que es también posible crear reglas de filtrado con iptables. Así pues es posible aceptar solo el tráfico que las políticas de seguridad de la empresa dictaminen, por ejemplo HTTP/s. Adicionalmente sería posible añadir filtrado de contenido en el trafico web, un antivirus perimetral o lo que se quisiera.
También, es posible crear reglas de filtrado por usuario o rol, es decir, podemos asignar IP estáticas a los clientes del VPN y aplicar reglas en función de la dirección origen.
Con este modelo se consigue 4 cosas:
- Que todo el tráfico vaya cifrado
- Que se pueda controlar de manera centralizada qué tráfico es aceptado y cuál debe ser filtrado
- Crear reglas en función de un perfil o usuario determinado
- Tener visibilidad y poder analizar todo el tráfico en caso de que el smartphone sea comprometido (o porque las políticas de seguridad así lo requieran)
Para establecer el túnel con OpenVPN es necesario únicamente instalar el binario (o compilar) en la máquina linux ya que la ROM de Android antes mencionada ya incluye OpenVPN. A la hora de establecer el túnel es posible hacer uso de certificados o usar una clave privada compartida. Evidentemente, para un entorno corporativo lo aceptable es el uso de clave pública.
El manual de como configurar la CA (autoridad de certificación) para generar certificados y usarlos con OpenVPN lo podéis encontrar en este link. Sin entrar mucho al detalle los pasos importantes para crear la CA y los certificados son:
- Editar el fichero 'vars' para configurar los datos de los certificados (país, ciudad, correo, etc)
- Inicializar la PKI y crear la CA con los comandos ./vars; ./clean-all; ./build-ca
- Generar el certificados del servidor OpenVPN con el comando ./build-key-server server
- Para cada cliente que queramos que se conecte, hay que generar un certificado con el comando ./build-key client1
- Generar el fichero que se usara para el intercambio de claves con Diffile Helman mediante el comando ./build-dh
Con esto ya tendremos los ficheros necesarios.
El único paso restante es mover el certificado del cliente, la clave privada y el certificado de la CA a un único fichero con formato 'p12' para poder integrarlo de manera sencilla con Android. Este fichero debe estar protegido con contraseña.
El comando para crear el fichero es:
openssl pkcs12 -export -in client1.crt -inkey client1.key -certfile ca.crt -name cert-master -out client1-all.p12
Una vez tenemos solucionado la parte de los certificados hay que configurar el servidor OpenVPN mediante el fichero server.conf. Básicamente, lo que hay que configurar son los siguientes parámetros:
- local X.X.X.X # dirección IP del servidor
- port 80 # puerto donde escucha el servidor VPN
- proto tcp # protocolo
- dev tun # interfaz del tunel (no está en modo bridge)
- ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt # ubicacion del fichero de la CA
- cert /etc/openvpn/easy-rsa/2.0/keys/server.crt # ubicacion del fichero del servidor
- key /etc/openvpn/easy-rsa/2.0/keys/server.key # ubicación de la clave del servidor
- dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem # ubicacion del fichero del Diffie Hellman
- server 172.16.1.0 255.255.255.0 # red asignada al VPN
- push "route 0.0.0.0 0.0.0.0" # rutas que irán através del VPN
- client-config-dir ccd # directorio con los ficheros que mapean las IPs por usuario/certificado
- cipher AES-256-CBC # algoritmos de cifrado simétrico, clave privada, etc
- comp-lzo # habilitación de la comprension
Aquí hay que destacar que se eligió el puerto 80/TCP en lugar del estándar de OpenVPN 1194/UDP para saltarse los firewalls en los puntos WiFi que estén filtrados. Es cierto que puede existir sitios donde haya filtrado de contenidos en el tráfico web mediante proxys con lo que podría fallar, pero siempre se pueden usar otros puertos.
La ruta 0.0.0.0/0.0.0.0 es necesaria para enrutar todo el tráfico por el VPN y así conseguir nuestro objectivo.
Para configurar el cliente OpenVPN en Android es tan sencillo como importar el fichero p12 a la tarjeta SD y desde la aplicación OpenVPN de Android abrirlo (hay que introducir la password configurada anteriormente). Luego, a través de las opciones de configuración es necesario seleccionar la IP del servidor VPN, puerto/protocolo y los valores para la clave simétrica: AES con 256 bit en modo CBC.
Con esto ya se tiene configurado el túnel VPN y lo único que falta es implementar las políticas de firewall en ambos endpoints.
En Android es sencillo usar iptables si se tiene acceso a la shell, así pues podemos crear un script con las políticas de firewall con el siguiente contenido:
#!/system/bin/sh
/system/bin/iptables -F
# Aceptamos el tráfico a lo
/system/bin/iptables -A INPUT -i lo -j ACCEPT
/system/bin/iptables -A OUTPUT -o lo -j ACCEPT
# Política por defecto
/system/bin/iptables --policy INPUT DROP
/system/bin/iptables --policy OUTPUT DROP
/system/bin/iptables --policy FORWARD DROP
# Reglas para el tráfico aceptado
/system/bin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
/system/bin/iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -p 6 --sport 22 -j ACCEPT
# Tráfico del tunel VPN
/system/bin/iptables -A INPUT -i tun0 -p 6 --dport 22 -j ACCEPT
/system/bin/iptables -A INPUT -i tun0 -p 1 -j ACCEPT
# Tráfico hacia el endpoint para establecer el túnel
/system/bin/iptables -A OUTPUT -d x.x.x.x/32 -j ACCEPT
# Trafico que va por el túnel
/system/bin/iptables -A OUTPUT -o tun0 -j ACCEPT
Ahora es necesario crear las reglas en el VPS. Estas incluyen reglas para hacer en forwarding del VPN hacia el interfaz público, reglas de NAT para salir a Internet y las políticas de filtrado que en este caso no he aplicado y las dejo a gusto del consumidor:
#!/bin/sh
/sbin/iptables -F
# Tráfico de/hacia localhost y el VPN aceptado
/sbin/iptables -A INPUT -i lo -j ACCEPT
/sbin/iptables -A OUTPUT -o lo -j ACCEPT
/sbin/iptables -A INPUT -i tun0 -j ACCEPT
/sbin/iptables -A OUTPUT -o tun0 -j ACCEPT
# Política por defecto.
/sbin/iptables --policy INPUT DROP
/sbin/iptables --policy OUTPUT ACCEPT
/sbin/iptables --policy FORWARD ACCEPT
# Tráfico aceptado hacia los puertos 80 y 443
/sbin/iptables -A INPUT -i eth0 -p 6 --dport 80 -j ACCEPT
/sbin/iptables -A INPUT -i eth0 -p 6 --dport 443 -j ACCEPT
/sbin/iptables -A INPUT -p ALL -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# NAT / Forwarding para el tráfico del VPN a Internet
/sbin/iptables -A FORWARD -i tun0 -j ACCEPT
/sbin/iptables -A FORWARD -i tun0 -s 0.0.0.0/0.0.0.0 -d 0.0.0.0/0.0.0.0 -j ACCEPT
/sbin/iptables -A FORWARD -i eth0 -o tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Con esto ya se tiene configurado el túnel, las políticas de firewall en el smartphone para forzar el tráfico a través del túnel y la política en el endpoint para enrutar el tráfico hacia Internet.
1 comentario :
Buenísima serie. Esperando con ganas tenerla completa.
Echaba en falta una buena guía sobre la integración de estos cacharros en redes empresariales ¿y en servicios de directorio?
Gracias por compartir.
Publicar un comentario