29 agosto 2011

Gmail Security Center

Gmail, el servicio sobre el que pivotan otros tantos servicios de Google y que mucha gente emplea como 'cuenta principal' y tienen asociada a servicios como Twitter, Facebook o cosas mas serias como bancos, compañías telefónicas, servicios de hosting, etc.

Se podría decir que para mucha gente es su activo mas valioso en su 'ciber-vida', por lo que protegerlo debería de ser algo importante.

Hace algún tiempo liberamos una pequeña guía de seguridad para Gmail y hoy vamos a presentar una herramienta que permita monitorizar el uso de una cuenta en Gmail.

Como probablemente todo el mundo sepa, Gmail tiene de serie un histórico de uso que permite comprobar el uso reciente de la cuenta


El problema es que solo registra los 10 últimos accesos, por lo que, o tomas la sana costumbre de revisar esa información casi a diario, o probablemente perderás información. No existe forma de consultar un histórico de actividad mas allá de esos 10 últimos accesos.

Dándole un par de vueltas a esto se me ocurrió crear una herramienta que hiciese tres cosas:
  • Poder generar un histórico de accesos a la cuenta virtualmente 'infinito' para consultar los accesos según fuese necesario
  •  Ampliar la información que ofrece Gmail, no solo con IP / País sino también ciudad e ISP
  • Tener la posibilidad de enviar alertas en función de la nueva actividad que se generase en esa cuenta (accesos)
Y la solución a esos problemas la he llamado 'Gmail Security Center' y está basada en este excelente ejemplo sobre como usar el módulo 'mechanize' en Python que he modificado para acceder a la información de actividad, añadido soporte para enviar 'tweets' para las alertas en tiempo real e incorporado el uso de Geolocalización .

# This Python file uses the following encoding: latin-1

import mechanize
import cookielib
import re
import sys
import getpass
import time
import GeoIP
import commands
import tweepy

#Twitter Auth

CONSUMER_KEY = ''
CONSUMER_SECRET = ''
ACCESS_KEY = ''
ACCESS_SECRET = ''

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
api = tweepy.API(auth)

#Geoip

gi = GeoIP.open("GeoLiteCity.dat",GeoIP.GEOIP_STANDARD)

# Browser
br = mechanize.Browser()

# Cookie Jar
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)

# Browser options
br.set_handle_equiv(True)
#br.set_handle_gzip(True)
br.set_handle_redirect(True)
br.set_handle_referer(True)
br.set_handle_robots(False)

# Follows refresh 0 but not hangs on refresh > 0
br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)

# User-Agent (this is cheating, ok?)
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]

# The site we will navigate into, handling it's session
br.open('http://gmail.com')

# Select the first (index zero) form
br.select_form(nr=0)

# User credentials

print "Gmail Security Center [ Security By Default http://www.securitybydefault.com ]"

login = raw_input("Login:")
password = getpass.getpass("Password: ") 

br.form['Email'] = login
br.form['Passwd'] = password

# Login
br.submit()

req = br.click_link(text='Información detallada')
br.open(req)

ips = []

while 1==1:

    html = br.response().read()

    ipscitas = re.findall('(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})', html)

    if ipscitas:
        
        for resultado in ipscitas:
        
            if not ips.count(resultado):

                ips.append(resultado)
                
                command_str = 'whois %s | grep "desc"' % resultado
        
                whoisret= commands.getoutput(command_str)
        
                whoisret = whoisret[1:-1].split('\n')
        
                m =re.search("(escr|descr):          (.+)",  whoisret[0])
        
                isp= m.group(2)
        
                gir = gi.record_by_name(resultado)
        
        
                if gir != None:
            
                    print resultado, gir['country_name'],  gir['city'], gir['region_name'], isp
                    
                    twittersend = resultado + " " + str(gir['country_name']) + " " + str(gir['city']) + " " + str(gir['region_name']) + " " + isp
                    
                    try:
                        api.send_direct_message(screen_name= '@YJesus', text = twittersend )
                        
                    except :
                
                        pass
    
    br.reload()

    time.sleep(900)


Para poder usarlo, primero debéis tener instalado en el sistema el módulo 'mechanize', lo mas fácil para instalar ese y otros módulos ajenos al core de Python es usar el comando -como root- 'easy_install' disponible en el paquete python-setuptools (al menos en Fedora)

# easy_install mechanize

Una vez instalado ese módulo, hay que dar soporte GeoIP instalando la librería en C de Maxmind y su bind a python (información para hacerlo aquí) y descargar una base de datos actualizada

Finalmente, viene la parte mas engorrosa de todo el asunto y es que Twitter, cuando forzó a usar OAuth en todo aquello que tuviese que interactuar con el, hizo que enviar tweets desde una aplicación fuese un proceso bastante laborioso. Aquí hay un tutorial bastante bueno sobre como registrar una aplicación hecha en Python para poder usar Twitter

De lo que se trata es de poder rellenar los siguientes campos en el script:

CONSUMER_KEY = ''
CONSUMER_SECRET = ''
ACCESS_KEY = ''
ACCESS_SECRET = ''

Una vez hecho eso, el script monitorizará la actividad de la cuenta GMail y cuando vea nueva actividad enviará alertas parecidas a esta:

Que serán cómodamente recibidas y procesadas vía Twitter, adicionalmente se puede sacar un histórico volcando la salida del script a un fichero

19 comments :

Borja Ferrer dijo...

Me encanta la idea, pero como buen luser, me muevo en entornos windows, como exportarlo para windows? Hay algun modulo parecido para entornos Visual Studio para que pueda picarmelo yo? Es que me parece una idea excelente!

Silverhack dijo...

Gran post Yago.... Tienes unas ideas cojonudas!

yago jesus dijo...

 Siendo Python, debería funcionar en Windows, sin haberlo probado yo identifico al módulo GeoIP como el más problemático, pero he visto hay uno 'pure-python' que si que debería funcionar. A ver si saco un rato y lo pruebo

yago jesus dijo...

Muchas gracias amigo !

errepunto dijo...

¿Un módulo para GeoIP 100% Python? Po'l amol del cielo, ¡compártalo! :)

Profesor22 dijo...

peor el remedio que la enfermedad al guardar u loginpass en claro

yago jesus dijo...

Hola, me encanta que comentes sin haber probado o/y entendido la herramienta, eso me da pábulo a poder explicártelo: Si te fijas, para pedir el login/pass de la cuenta de Gmail empleo login = raw_input("Login:")
password = getpass.getpass("Password: ") que, básicamente lo que hace es pedirlo por cada ejecución del programa con lo que no se guardan datos de acceso a la cuenta.Saludos
 

yago jesus dijo...

 Aquí está http://code.google.com/p/pygeoip/

Invitado dijo...

La unica pega que le veo es que solo funciona con la cuenta en español, es facil de cambiar, pero estaria bien que fuese algo mas facil de hacer funcionar en otros idiomas...

Yago Jesus dijo...

 Hombre, es realmente sencillo adaptarlo, por ejemplo para una cuenta en Inglés es cambiar donde pone '
req = br.click_link(text='Información detallada')' por req = br.click_link(text='Details')

errepunto dijo...

¡Muchas gracias! Me lo apunto.

Profesor22 dijo...

disculpa, tienes razón, aunque si hay que ejecutarlo manualmente pierde el 99% de la gracia. no te lo tomes a mal.

Tekenji Washirio dijo...

Y en el caso de que que la cuenta tenga activado la dos pasadas de verificación como haría el requerimiento de las password únicas
 que se pueden generar para este tipo de aplicaciones  ? 

errepunto dijo...

Ahora sería interesante "tunear" el script para que funcione sobre GAE, y así poder tenerlo siempre activo sin preocupaciones... Ya tengo diversión para una tarde de aburrimiento :)

Borja Ferrer dijo...

Gracias Yago, yo tb mirare de sacar un ratito en ksa a ver si lo pruebo, aunque debo decir de antemano que no he trabajado en pyton pero algo hare ya veras... jejejejejejeje Gracias una vez mas.

Las Cosas De Alan dijo...

Y con esto no estaríamos haciendo publica de alguna manera nuestra información al publicar en Twitter estos Datos que de una u otra forma es sensible???.
Por que mas bn no enviar un mensaje privado o una alerta a nuestro Android por medio del Wath's App o algo asi ???

Yago Jesus dijo...

El mensaje que te llega es un 'mensaje directo' hacia ti, totalmente privado

j0rs dijo...

Desconocía mechanize (y alguno que otro módulo más), gracias por eso y por el script :)

Por cierto, supongo que es cuestión de costumbres, pero el bucle infinito del while 1==1 lo prefiero con algo como while True (ganas en legibilidad, que para eso es grande Python).

Jucalg dijo...

Buenas buenas en primer lugar no es una solucion muy funcional para la mayoria de la gente que deseea hacer este tipo de procedimiento ya que esto es solo para usuarios avanzados y al final de cuentas son mas los usuarios que tienen un simple correo y sean usuarios basicos, en conclusion no es nada revolucionario y no lo digo por mi sino por que hablo por los usuarios del comun que no van a entender un carajo lo que usted esta proponiendo para implementarlo
saludos y espero en una proxima ocasion no piense solo en usuarios avanzados como nostros sino en cualquier persona. Le pongo un ejemplo mi madre tiene correo de gmai y le encantaria aplicar esto pero si no es por que yo le ayudo ella no va a saber que hacer