11 de octubre de 2009

Lista de Password

Tras leer en varios sitio sobre la publicación de más de 10.000 contraseñas de cuentas de correo, y tras confirmar por distintas fuentes que las contraseñas suelen ser las mismas y que en su mayor parte son simples de sacar con un ataque de fuerza bruta por diccionario, me he propuesto hacer un diccionario ordenado por probabilidad de aparición de las contraseñas.

Se que existen infinidad de diccionarios en muchos sitios (http://passwords.openwall.net) pero yo quiero crear uno bastante reducido, para tardar a menos y realizar el menor numero de intentos posibles.

¿Porque usar diccionarios?


Existen varias razones pero las dos principales son estas:

  • La primera es la más clara, intentar probar todas requiere demasiado tiempo. El calculo es simple, simplemente hay que hacer la variación con repetición. He realizado un test empírico de un algoritmo que calcula 10000 contraseñas (solo números) tarda 0.047 segundos y por tanto en generar y probar un millón vamos a suponer que tarda 5 segundos; con estos cálculos aproximados veamos la siguiente tabla:

    Tamaño Posibles (85)Tiempo (85) Posibles (26)Tiempo (26)
    4 caracteres52 millones4,33 minutos456.9762,28 segundos
    5 caracteres4.437 millones6,16 horas11 millones59,40 segundos
    6 caracteres377.149 millones21,83 días308 millones25,74 min
    7 caracteres32 billones5,07 años8.031 millones11,15 horas
    8 caracteres2.724 billones4,31 siglos208.827 millones12,08 días
    9 caracteres231.616 billones36,6 milenios5 billones10,47 meses
    10 caracteres19 trillones3010 milenios141 billones22,69 años
    11 caracteres1.673 trillones265070 milenios3.670 billones5,9 siglos

    NOTA: 2x(26 Letras + ñ) + (21 caracteres especiales [!|"@.#$~%&/()=?¿'*+] ) + (10 digitos) = 85
    Como se observa en la tabla cuando la contraseña tiene más de 5 caracteres el tiemplo empleado para obtener la contraseña es de más de una semana, tiempo de sobra para ser detectados sin problema.

  • Otra de las razones por las que realizar un diccionario está relacionado con el modo que tenemos de recordar las personas. Dado que recordar "E46!fhJd9@" nos resulta muy complicado usamos otras contraseñas simples de recordad, normalmente palabras que existen. Por tanto podemos reducir el número de intento a tantas como palabras hay en el diccionario, más de 160 mil palabras según la rae, lo que reduce en numero de posibles claves.Lo mejor a la hora de usar diccionarios es realizar uno personalizado para cada objetivo, no es igual intentar sacar el password de un ingles o americano que de un egipcio o un español, ya que las palabras que usarán serán distintas.


Creación del Diccionario


Para crear mi diccionario he cogido los datos desde los siguientes sitios:

  1. Top 10 contraseñas de PC Magazine

  2. Contraseñas más usadas de las publicadas de "Flirtlife.de"

  3. Contraseñas más usadas en las publicadas de "Hotmail.com"

  4. Contraseñas por defecto de los Routers


Para que me resultara más simple la creación del diccionario he programado en python un simple código para ordenar:
'''
Programa que descarga y ordena las contraseñas más por defecto de los routers
@author: ehooo
'''

import httplib, os
from HTMLParser import HTMLParser
class ParseTable(HTMLParser):
'''
Parser para obtener los datos de la columna indicada
'''

def __init__(self, columna):
HTMLParser.__init__(self)
self._columna = columna
self._colAct = 0
self._data = False
self._fin = True
self.lista = {}

def handle_data(self, data):
if self._data:
dato = str(data)
if dato in self.lista:
self.lista[dato] += 1
else:
self.lista[dato] = 1
self._data = False

def handle_starttag(self, tag, attrs):
if self._fin:
if tag == "table":
self._fin = False
elif tag == "tr":
self._colAct = 0
elif tag == "td":
if self._colAct == self._columna:
self._data = True
self._colAct += 1

def handle_endtag(self, tag):
if self._fin:
pass
elif tag == "tr":
self._colAct = 0
elif tag == "table":
self._fin = True

if __name__ == '__main__':
conn = httplib.HTTPConnection("www.phenoelit-us.org")
conn.request("GET", "/dpl/dpl.html")
res = conn.getresponse()
if res.status == httplib.OK:
html = res.read()
p = ParseTable(5)
p.feed(html)
lista = p.lista
n_elem = len(lista)
list = {}
try:
while True:#Cuando se queda sin elementos lanza una Excepcion "KeyError"
(key, valor) = lista.popitem()
if valor in list:
list[valor] += ", "+str(key)
else :
list.setdefault(valor, str(key))
except(KeyError):
valores = list.keys()
valores.sort()
valores.reverse()
ord = []
for valor in valores:
ord += [list[valor]]
elem = 0
for passwords in ord:
porcentaje = (valores[elem]* 100) / n_elem
print valores[elem],"de",n_elem,"son",porcentaje,'% ->',passwords
elem += 1
else:
print "ERROR en la descarga"

La lista que he obtenido ha quedado reducida ha 46 palabras, cogiendo las más comunes de los routers y de las personas; eliminando ciertas passwords sin demasiada relevancia. Puedes descargar el diccionario desde http://rollanwar.net/pass+usados.txt. De todos modos puedes crear el diccionario de routers usando parte del código publicado.

Otros datos de interés:
http://onemansblog.com/2007/03/26/how-id-hack-your-weak-passwords/

No hay comentarios:

Publicar un comentario