17 abril 2013

La mentira de los "puntitos" en Android



Tu contraseña está segura en tu teléfono Android. Lo he visto yo. Pone puntitos en la casilla, eso es seguro FIJO.


Pone "·········" en la casilla dónde la pusiste anteriormente. Así que nadie la puede ver. Bueno... depende.

Los datos de las WiFis en Android no se cifran de ninguna manera. Si bien puede ser algo delicado depende en que entornos, es útil en cierto modo...

Al margen de poder ver la contraseña en los ajustes, con la casilla "Mostrar contraseña"; podéis verlas en el fichero "/data/misc/wifi/wpa_supplicant.conf", con este formato tan chulo:


network={
  ssid="BatWifi"
  psk="c4tw0m4n1sh0t"
key_mgmt=WPA-PSK
priority=3
  }

Pero, las credenciales de las VPNs almacenadas en Android... ¿cómo almacenan los datos?

@Chencho dijo: "(...) están en /misc/data/keystore (creo) y parece que están cifradas con cosas gordas y caras."

Pregunté por ahí a ver si alguien sabía de la existencia de una manera de "desvelar" contraseñas de las VPNs almacenadas (Gracias a @ldelgadoj y a @0xroot por la info), y a nadie le sonaba nada... Echemos un vistazo.


Si nos asomamos a "Ajustes > VPN > VPNBorjamari", al contrario que con las claves de redes WiFi:


  • No hay casilla de "mostrar contraseña"
  • Seleccionar el texto no da la opción de copiar/cortar. (Menú contextual capado)
  • Arrastrar la selección a la casilla de usuario (por ejemplo) no hace más que mostrar los "puntitos".

¿No se puede copiar?

Bien hecho Android, guardar en plano la contaseña de acceso a una VPN, quedaría feo... Pero...

Un día, usando la aplicación WifiKeyboard (un teclado que ofrece un interfaz web para poder escribir al teléfono) encontré una opción que se define como:


"Edit text locally:"


Si pulsas la tecla F4, te "trae" el contenido de la caja de texto que tuvieras seleccionada en el teléfono para que lo puedas editar en el navegador, y volver a mandarlo al teléfono. ¡ QUE ÚTIL !


Pero... ¿si lo hago en una casilla de contraseña? Yo di por hecho que ejecutaría un "copy" en el teléfono, y pegaría el resultado en el navegador, con su correspondiente string de "·········".


Sin embargo, cual fué mi sorpresa, que al pulsar F4 mientras tenía seleccionado el campo de la contraseña de mi VPN casera, ¡ me mostró la clave en plano !

Vaya. Aquí pasa algo. Lo interesante será, saber EL QUÉ.

Lo que me facilitó MUCHO las cosas fué que el proyecto es de código abierto :D (Para que luego digan que el open source no vale para nada ¬¬) Está disponible aquí: https://code.google.com/p/wifikeyboard/
Bueno, al turrón. Vamos a ver que pasa cuando le damos a la tecla F4... Empecemos con lo fácil, Zaproxy + Interfaz web del WifiKeyboard:

Al pulsar F4 se realiza una petición HTTP a "http://IPDELTELEFONO:1111/text" (sin datos por POST ni nada "extra") que devuelve en plano el texto contenido en la casilla donde nos encontremos en el teléfono.

En el código fuente del interfaz en HTML, se procesa que en el get esté "/text" y una vez encontrado, llama a local_input(), que es donde lee que la tecla pulsada sea F4 (En Javascript el keycode 115):



Que a su vez llama a submit_text()... que finalmente acaba pasando la petición a una clase en Java del tipo InputMethodService, que nos va a permitir usar los métodos que interactúan con el teclado.

Y finalmente, llegamos a la función clave:



Lo que ocurre aquí, es más o menos lo siguiente: 

Se crea un objeto de tipo ExtractedTextRequest, que será utilizado para llamar con el cómo parámetro al método getExtractedText(), de la interfaz InputConnection.

Una vez establecidos los parámetros necesarios del objeto ExtractedTextRequest, se llama a la función "getExtractedText(ExtractedTextRequest request, int flags)", que según la documentación oficial, hace esto:
"Retrieve the current text in the input connection's editor, and monitor for any changes to it."
Lo castea a String... y ¡ TACHÁN ! ya tenemos nuestro contenido :D

Al no ejecutar el "copy", Android no copia los puntos. En lugar de "copiar", "extrae" el texto de la selección, que como voy a demostrar, está en plano realmente.
Bueno, una vez visto esto... ¡ vamos a hacer una pequeña app para poder usarlo en local !


PoC

Después de mirar y rebuscar, teniendo en cuenta que es la primera vez que programo algo para Android... (quiero agradecer a Iban su paciencia en enseñarme lo que se de Java, si no, no hubiera podido ni leer el código) vi que la mejor manera de hacer el PoC era con el teclado de muestra que viene con el SDK, que provee un IME (Input Method Editor) enterito y busqué una manera de "disparar" la función getExtractedText().

La solución ha sido onKeyDown() dentro del fichero .java que nos da la demo del teclado de Android "SoftKeyboard.java":



Por lo tanto, mientras tengamos seleccionado como input nuestro teclado "especial", la tecla "MENU" lanzará ese código que hemos definido, mostrando, en este caso, la contraseña de nuestra VPN:



Claro, imagínate que ves algo así, preguntas a la gente... y nadie sabe nada... ¡ Oh dios ! ¡ Lo he encontrado yo !

Y como buena persona que soy, un "responsible disclosure" estaría bien, así que mandé un mail a security@android.com.



Tras decirme en el primer email, que me agradecían el aviso, que lo iban a mirar y se pondrían en contacto conmigo... cito la respuesta final:

"Looking into this more we believe this is intended behavior, since an IME must be able to interact with text already entered in text fields."
Vaya, he dado con una "feature"... que decepción. Sinceramente, viniendo esa respuesta de la empresa que viene, no me la esperaba en absoluto. ¿Una "feature" poder acceder a las credenciales de una VPN?

Pero, si es una funcionalidad, ¿por qué está capado el menú de copiar y pegar?
¿Por qué no hay una casilla de "mostrar contraseña"?
Aunque lo fuera... no me parece una buena práctica el poder ver las contraseñas de las VPNs almacenadas...

En resumen, no se si alguien sabía esto. Igual resulta que se puede incluso habilitar un botón de "Mostrar contraseña" para las VPNs y yo no lo sabía... De todas maneras, aquí he escrito algo para que os entretengais un poco y encima os regalo el APK para que mireis vuestras contraseñas por si se os olvidan.

Como parte de una auditoría, el obtener las credenciales de una VPN corporativa en un teléfono Android... me parece que menos que útil.

Esta "función extra" del teclado la he probado con unos cuantos inputs "ocultos" como el campo donde se escribe el pin de desbloqueo en los ajustes o en algún otro campo. Es útil si tienes que escribir una contraseña larga y no sabes si te has equivocado :D

Bueno, os dejo el .apk y ¡ Espero que a alguien le sea de ayuda !


P.D.: Es un .apk autofirmado que es el "SoftKeyboard" incluido de muestra en el SDK de Android y SÓLO tiene añadida la función de sacar en una alerta Toast con el contenido de la casilla donde se encuentre el usuario posicionado. Si no os fiais (normal) podeis hacerlo vosotros mismos con el "SoftKeyboard" que viene con los ejemplos del SDK de Android.


------------------------------


Artículo cortesía de Borja Berástegui

13 comments :

María García dijo...

Está muy bien el artículo. Ahora mismo voy a probarlo. Pero mi teclado es uno ramplón y no encuentro la F4.
(No sé por qué sigue saliendo mi foto en el g+ de las narices si ya la he quitado)

María García dijo...

En mi terminal el /data está protegido (no lo tengo rooteado)

Pajaro121 dijo...

Pero bueno, los tunnelgroups , históricamente al menos en cisco , han sido facilmente reverseables ¿no?, nadie está tan chalado como para poner su user y pass en el dispositivo.
Y ademas las VPN molonas usan OTP para el user ¿no? y si no es así deberían.

Borja Berastegui dijo...

Perdón por no poner la aclaración de que para leer los datos de las Wifi almacenadas hay que tener el teléfono rooteado :S

Pero bueno, iba al hecho de que no están cifradas ;)

Borja Berastegui dijo...

Bueno, pero ya sabemos como es el "deberían" en estas cosas :P

Y desde luego, basado en la premisa de "nadie está tan chalado"... Uy, eso si que no, la gente hace cosas mucho peores.

De todas formas, es una manera de recordarle a la gente que no debería hacer caso omiso de las recomendaciones como guardar el user/pass en el dispositivo, por ejemplo; por lo que he puesto en el post.

María García dijo...

Uy; rootear el móvil. Eso yo no vuelvo a hacerlo.
Ya me imagino q hay muchas cosas q no van cifradas (aunque deberían). Pero no está de más saberlo.
(veo q ya sale la foto cambiada; esto del g+ no hay quién lo entienda)

Javier dijo...

Parece lógico que un IME de teclado pueda acceder a lo que estás tecleando. Por eso, cuando lo habilitas te sale un mensaje de confirmación, que te avisa de que ese teclado podrá ver todo lo que teclees, y si es malicioso estás básicamente j*****.

Sergio dijo...

Estoy convencido que en tu andadura has aprendido mucho, que es lo importante. Y me alegro.


Sin embargo, y perdona que lo diga, no me parece una cosa alarmante. El artículo expone que desde un IME se podría acceder a la contraseña en plano. Claro, ¿cómo si no se podría editar ese campo de texto? Un problema sería si sí se pudiera mostrar la contraseña como en las redes wifi con un simple checkbox.


Luego lo que haces es demostrarlo tomando el control del teclado... ¡implementando tu propio teclado! Es que sigo sin ver el riesgo/fallo en todo esto.


Un saludo!!

Reaper dijo...

¿Pero es que estamos tontos? ¿Cómo pretendes programar un IME sin acceso a la maldita casilla de texto?

¿Y cómo pretendes que un programa cifre contraseñas recordadas de redes wifi AJENAS AL DISPOSITIVO? ¿Hardcodeando el password de cifrado? Ah no, que eso es el cáncer de la seguridad, entonces algún listillo sacaría un programa para descifrar eso y Android sería el peor SO de la historia de la humanidad.

dudu dijo...

En iph0ne tambien se guardan en plano, era de esperar que en Android tambien! Buen post!

dudu dijo...

El problema es la via de conexion, es decir via WiFi

Borja Berastegui dijo...

Os respondo a los últimos comentarios a la vez, que van todos por el mismo camino.

El problema no es el acceso a la casilla de texto cuando la estamos introduciendo, SI NO A LAS YA ALMACENADAS.

Si tú guardas la configuración de una VPN en tu teléfono Android, no se debería poder acceder a las credenciales POSTERIORMENTE de ninguna manera, ahí el problema.

Si tu pierdes tu teléfono por ejemplo, yo con este "método" podría obtener el usuario/contraseña de acceso a la VPN de, por ejemplo, tu oficina. Algo que creo que en ningún caso debería ser posible.

Si teneis alguna duda más, para eso estoy ;)

¡ Un saludo !

chencho dijo...

Tiene huevos que necesite esto ahora y no funcione en mi terminal. Instalo tu app lleno de malware y viruses, pero al acceder a las casillas de texto con punticos, no aparece la contraseña. TONGO! :D