viernes, 11 de enero de 2013

Data (Un)Protection en iOS

NOTA: Est post lo publiqué hace unos días en el blog de S21sec, pero lo pongo también aquí para tener todos mis posts "juntitos".

Para los que no estén familiarizados con los sistemas iOS: Data Protection es uno de los mecanismos que ofrece Apple para proteger la información crítica que es almacenada internamente en el dispositivo. Su objetivo es evitar que contraseñas, certificados u otro tipo de información sea recuperada de un dispositivo perdido o robado. Para ello, Apple ha creado una serie de clases mediante las cuales es posible cifrar la información de diferentes maneras en función de su necesidad de accesibilidad: 
  • When unlocked: La información se encuentra cifrada con una clave derivada del UID (clave única del dispositivo) y del Passcode elegido por el usuario, por lo que únicamente es accesible después de que el dispositivo haya sido desbloqueado por el usuario. 
  • While locked: No es habitual, pero está pensado para información que deba ser accedida mientras el dispositivo está bloqueado. 
  • After first unlock: Es muy similar a "When unlocked", con la diferencia de que la clave de cifrado, derivada del UID y del Passcode, no es eliminada de la memoria al bloquear el dispositivo. 
  • Always: La información se encuentra cifrada únicamente con el UID, con lo que es posible acceder a ella siempre, pero únicamente desde este dispositivo, ya que el UID es único a cada dispositivo iOS y este no es accesible por software. 
Los desarrolladores son, por lo tanto, responsables de escoger el tipo de protección que quieren para la información de sus aplicaciones. En el caso de la propia Apple, según indican en el documento oficial de seguridad en iOS, estos son los aplicados:


Como sucede siempre, la usabilidad se encuentra reñida con la seguridad, así que nos encontramos con que si queremos permanecer conectados a una Wifi, recibir correo electrónico, recibir mensajes instantáneos, etc, es necesario que sus claves sean accesibles aunque el dispositivo se encuentre bloqueado. Al menos, la accesibilidad "After first unlock" hace que, tras un reinicio, sea necesario introducir el Passcode una primera vez para que esta información se encuentre disponible.

Sin embargo, si un desarrollador no tiene cuidado con la clase elegida, puede encontrarse con que su información podría ser accedida sin necesidad ni tan siquiera de averiguar el Passcode empleado por el usuario. Es el caso, por ejemplo, de los certificados VPN, que como podemos ver les está asignada una accesibilidad "Always", lo cual quiere decir que son accesibles en cualquier momento, aunque nadie haya introducido el Passcode.

Si hemos obtenido el control de un dispositivo iOS, una de las acciones que podemos querer realizar es volcar el contenido del KeyChain, que es donde se almacenan las credenciales, como por ejemplo las de Wifi o los propios certificados de la VPN. Para ello podemos usar la herramienta iphone-dataprotection que debemos ejecutar desde el propio dispositivo, para que este pueda descifrar usando el propio UID:

# ./keychain_dump
Writing 10 passwords to genp.plist
Writing 0 internet passwords to inet.plist
Writing 6 certificates to cert.plist
Writing 3 keys to keys.plist


Esto nos va a devolver toda la información a la que podemos acceder en nuestra situación actual. En este caso se trata de un iOS que se encuentra bloqueado con Passcode, pero que ya ha sido desbloqueado una primera vez, así que si buscamos en los ficheros plist generados podremos ver, como comentábamos antes, algunos certificados VPN e incluso claves como puedan ser las claves de las Wifis a las que ha estado conectado:


Esto es todo lo que podemos obtener SIN conocer el Passcode del usuario pero... ¿y si podemos averiguarlo? ¿y si el usuario ha elegido un Passcode demasiado trivial? Eso ya será otro post.

martes, 11 de diciembre de 2012

5º Aniversario de Pentester.Es

Como ya anuncié en su momento, hoy hace exactamente 5 años que se publicó el primer post de Pentester.Es, un 11 de Diciembre de 2007: http://www.pentester.es/2008/08/nace-wwwpentesteres.html

El blog empezó como una idea entre tres amigos de publicar la información que obteníamos en nuestros "trasteos". De retribuir al mundo algo del conocimiento que habíamos adquirido de él. Luego, con el paso del tiempo, se ha convertido practicamente en un proyecto individual, aunque las contribuciones siempre han sido bien recibidas.

La frecuencia de publicación ha ido variando con el paso del tiempo, en función de la disponibilidad del editor (que no ha sido mucha), pero intentando siempre poner artículos interesantes, aunque fueran pocos.

Durante estos 5 años hay a mucha gente a la que agradecer que este blog que yo en un principio pensé que acabaríamos leyendo 4 amigos se haya convertido en un blog con muchos más lectores de lo que hubiera llegado a imaginar.

Me gustaría darles las gracias desde aquí a todas las personas que han contribuido con artículos, porque libera un poco de la carga de trabajo que supone la publicación de contenido de forma regular. También me gustaría agradecer a Yago Jesús, del blog SecurityByDefault (conocido por todos), porque fue el precursor del salto de este blog del estatus de "blog de amigos" a "blog público" gracias a un post titulado "Blogs interesantes de Seguridad" que publicó allá por el 2009 y que podéis leer AQUÍ.

Y por supuesto, y por encima de todo, gracias a todas las personas que leéis este blog y que comentáis los artículos, a pesar de que la frecuencia de ellos sea menor de la que nos gustaría, pero que seguís leyendo detenidamente cada cosa que escribimos.

Dicho esto, como sabéis y os comenté EN ESTE POST, este sábado es la celebración del cumpleaños. Las plazas ya están cerradas pero os dejo aquí el orden final de las charlas y sus títulos para los que ya estáis apuntados:

10:30 - 11:30 - "Un laboratorio GSM por menos de 100€" (José Picó & David Pérez).
11:30 - 12:30 - "What lies Internet beneath?" (Juan Garrido & Pepelux)
12:30 - 13:30 - "Criptografía en CTFs" (Dani Kachakil)

Tras estas charlas, nos iremos a comer una paellita con algún que otro picoteo como celebración, y después... estamos abierto a cualquier propuesta :)

Gracias a todos los que venís, y a los que no venís... con un poco de suerte nos veremos en el 10º aniversario ;)

martes, 6 de noviembre de 2012

Análisis de Tráfico SSL en Android 4.x


El post de hoy no trata de ninguna nueva técnica ni nada excesivamente sofisticado, sino más bien de algo que es conocido pero que la gente con memoria de pez como yo se ve obligado a buscar una y otra vez cuando necesita hacer algo.

Cuando queremos analizar una aplicación de Android, ya sea para hacer una auditoría o para analizar si tiene algún componente malicioso (en mi caso suele ser lo primero), una de las cosas que tenemos que mirar son los puntos de comunicación con el exterior. Uno de los medios de comunicación más habituales es el uso de HTTP para comunicarse con aplicaciones web externas o web services. Hasta aquí ningún problema, podemos suplantar el nombre empleando el módulo fakedns de Metasploit ([1] [2] [3]) e interceptar las comunicaciones empleando Burp Proxy, ZAP o cualquier otro a vuestra elección.

El principal problema ocurre cuando esta comunicación es HTTPS, ya que estos proxies lo que hacen es crear una CA interna y van generando certificados firmados por esta CA para cada web que visitas (el funcionamiento puede cambiarse, pero este es el que viene por defecto con Burp). Esta CA creada por Burp, evidentemente, no es de confianza para nuestro Android, así que se nos muestra un mensaje de advertencia como el que vemos arriba o, sencillamente, la aplicación que estamos auditando rechazará la conexión por no estar firmado el certificado por una CA de confianza.

Como muchas veces la aplicación no nos va a dejar que aceptemos este certificado, vamos a tener que hacer algo para que nuestro Android confíe en la CA de nuestro Burp, así que lo primero que vamos a hacer es obtener la clave pública de esa CA. La manera más sencilla es hacer que nuestro navegador estandar use el burp y visitar cualquier web por HTTPS. Si vemos el detalle de los certificados veremos que podemos exportarlos en varios formatos. Hagámoslo en PEM:


Ahora que tenemos el certificado habrá que subirlo de algún modo a nuestro dispositivo. Se puede hacer de varias formas, pero una de las más cómodas es usar el comando "adb" que viene con el SDK de Android:

$ adb push PortSwiggerCA.pem /sdcard/
107 KB/s (1038 bytes in 0.009s)

Ya lo tenemos subido ¿y ahora dónde lo metemos? En versiones anteriores de Android los certificados de las CAs de confianza se encontraban en un único fichero que debíamos bajar a nuestro equipo, añadir la nueva CA y posteriormente volverlo a subir. En el caso de Android 4 la cosa ha cambiado un poco, ahora tenemos una serie de ficheros en /system/etc/security/cacerts/ que contienen cada uno de ellos un certificado de una CA:

$ adb shell
shell@android:/ $ su
shell@android:/ # cd /system/etc/security/cacerts/
shell@android:/system/etc/security/cacerts # ls -la
-rw-r--r-- root     root         4767 2012-09-28 14:15 00673b5b.0
-rw-r--r-- root     root         4573 2012-09-28 14:15 03e16f6c.0
-rw-r--r-- root     root         5292 2012-09-28 14:15 08aef7bb.0
-rw-r--r-- root     root         4540 2012-09-28 14:15 0d188d89.0
-rw-r--r-- root     root         4614 2012-09-28 14:15 10531352.0
-rw-r--r-- root     root         4686 2012-09-28 14:15 111e6273.0
-rw-r--r-- root     root         5027 2012-09-28 14:15 1155c94b.0
-rw-r--r-- root     root         5345 2012-09-28 14:15 119afc2e.0
-rw-r--r-- root     root         5844 2012-09-28 14:15 11a09b38.0
[...]

Parece que, si disponemos de acceso root, debería ser tan fácil como colocar nuestro fichero PEM en este directorio ¿Con cualquier nombre? Pues no, cualquier nombre no vale. Esos números que vemos no son más que un hash del subject del certificado, y se usan como si fuera una tabla hash, es decir, cuando se obtiene un certificado que está firmado por una CA, se realiza el hash del subject de esta CA y se busca el fichero con este nombre. Si se producen colisiones en el hash se va incrementando el número de la extensión (.0 .1 .2 ...). Para obtener ese hash lo podemos hacer con openssl de la siguiente forma:

$ openssl x509 -noout -subject_hash_old -in PortSwiggerCA.pem
9a5ba575

Ahora solo nos quedará meter el certificado en el lugar indicado con el nombre adecuado. Para ello, depende del rooteo que hayamos hecho, es probable que tengamos que remontar en lectura/escritura la partición /system:

shell@android:/system/etc/security/cacerts # mount -o rw,remount /system
shell@android:/system/etc/security/cacerts # cat /sdcard/PortSwiggerCA.pem > 9a5ba575.0
shell@android:/system/etc/security/cacerts # mount -o ro,remount /system

Hecho esto ya solo tenemos que reiniciar el terminal y volver a repetir el proceso. Ahora cuando visitemos una página HTTPS a través de Burp, el navegador va a aceptar el certificado que éste le proporciona, y por tanto va a poder inspeccionar y modificar este tráfico.

Lo mismo va a ocurrir con las aplicaciones en las que no podíamos simplemente darle a "aceptar certificado", con lo que ya tenemos resuelto el problema de inspeccionar este tráfico.

Ahora quedaría mirar si, dentro de ese tráfico, podemos manipular la información o hacer algo con lo que vulneremos la seguridad de la aplicación, pero eso ya... es otra historia.