martes, 2 de junio de 2009

Cumpleaños, Picadillos y Seguridad web

Hasta ahora un problema recursivo de Velneo en la web son los formularios por método post, de no ser que hagas uso intensivo del plugin vPost para su envío.

Los problemas que he ido encontrando a lo largo de los años han sido: el proxy-caché de Telefónica, los antivirus que trastean con los paquetes TCP de forma "transparente", y últimamente el navegador Opera.

Las soluciones hasta ahora eran obvias: que no te mienta tu proveedor de internet y que tu antivirus "transparente" lo sea de verdad, pero para Opera no he encontrado solución sin utilizar vPost.

Con vPost y Opera aún experimento algunos problemas pero estoy en ello.

Como al parecer era un problema de protocolo me instalé un analizador de tráfico de red para poder ver los paquetes que viajaban entre el navegador Opera y el vServer. Analizando los paquetes pude ver que el navegador sí envía la información por post al vServer, pero usando el protocolo http1.1 en lugar del http1.0 que es el que soporta vServer.

El problema parece estar ahí y la solución debe ser vPost.

Ya que estaba mirando paquetes, vi que el formulario (nombre de usuario y contraseña) estaba mandando la contraseña como texto plano en el paquete, ya que no estaba en una conexión segura https.

Si necesitamos un entorno seguro lo que debemos hacer es montar un Apache intermedio haciendo proxy inverso delante del vServer.

Una buena solución para evitar que las contraseñas se manden en plano es encriptar la contraseña en el cliente con javascript antes de hacer el envío del formulario. En el servidor comparamos la contraseña encriptada recibida con la guardada en la base de datos y validamos.

Para ello tenemos dos opciones en la base de datos: guardar la contraseña encriptada, o guardarla como texto plano.

Por razones de seguridad; si alguien obtiene acceso indebido al servidor y a las tablas de datos, o entra un ladrón a la oficina y se lleva el disco duro, deberíamos guardar siempre las contraseñas encriptadas en la base de datos ya que así, aunque obtengan las contraseñas no podrán usarlas por estar encriptadas y no haber vuelta atrás.

Llegados a este punto mi principal preocupación pasa a ser la posible vuelta atras: es posible desencriptar las contraseñas?

Los algoritmos de encriptación suelen basarse en obtener resúmenes, hash o "picadillos" de la cadena original.

Usando algoritmos estandard de encriptación como md5 o sha, en teoría no es posible, aunque estos algoritmos presentan un problema: como su dominio es infinito (las posibles cadenas a encriptar) y su resultado sí es finito (cadenas de n bits de longitud) tienen posibles colisiones.

Una colisión es encontrar dos cadenas que encriptadas tengan el mismo resumen.

Es fácil encontrar una colisión?

En principio no es fácil, pero en los últimos años hay ejemplos publicados de colisiones md5; dos pdf's diferentes con el mismo md5, o incluso un equipo chino que dice hallar colisiones sha en tiempos muy inferiores a los estimados en teoría.

Para encontrar colisiones se usan tablas rainbow que son gigantescas tablas de cadenas originales con su hash, resumidas y vueltas a encriptar, resumidas de nuevo y vueltas a encriptar, etc.

La búsqueda de hashes de forma recursiva sobre estas tablas permite la obtención de colisiones en tiempos muy inferiores a la fuerza bruta.

Qué ocurre si encontramos colisiones? Que el algoritmo de encriptación queda debilitado y su uso para fines seguros queda en entredicho.

Ahora, no es lo mismo buscar dos cadenas cualquiera que tengan el mismo hash, que buscar otra cadena que tenga el mismo hash que una dada.

Aquí es donde entra a jugar el cumpleaños.

Cuál es el número mínimo de personas que deben reunirse en una habitación para que la probabilidad de que dos de ellas cumplan años el mismo día sea mayor del 50%?

Si definimos probabilidad de que suceda algo como el número de casos favorables dividido por el número de casos posibles, y si definimos como probabilidad del caso contrario como 1 - p, siendo p la probabilidad del caso positivo, preguntémonos cuál es la probabilidad de que las personas reunidas en una habitación no cumplan años el mismo día.

Para la primera persona la probabilidad sería 365 días posibles entre 365 días disponibles.

Para la segunda persona la probabilidad sería de 365 - 1 días posibles (los 365 del año menos la fecha del cumpleaños de la primera) entre 365 días posibles.

Para la tercera sería 365 - 2 entre 365, etc. Es decir,

p = (365/365) * ((365 - 1)/365) * ((365 - 2)/365)* ... * ((365 - n + 1)/365)

o sea,

p = (365!)/((365^n)*((365 - n)!))

Así pues, la probabilidad de que dadas n personas reunidas en una habitación, dos de ellas cumplan años el mismo día es 1 - p, y con n=22 ya obtenemos una probabilidad del 50,7%

Para 30 personas la probabilidad es más del 70%, para 40 casi del 90% y para 60 más del 99%

La probabilidad de que dada una persona en el grupo hallar otra que cumpla años el mismo día es mucho menor,

p = 1 - ((364/365)^n)

Necesitaríamos un grupo de 253 personas para que esa probabilidad sea mayor del 50%

Así las cosas, para una función criptográfica de 128 bits, para encontrar una cadena que tuviese el mismo hash que otra deberíamos probar 2^128 valores, pero para encontrar dos cadenas cualquiera que diesen el mismo hash sólo deberíamos probar 2^64 valores.

Son números grandes, pero a día de hoy, con los medios tecnológicos disponibles; PS3, portátiles más potentes que mi equipo de sobremesa para desarrollo, el cloud-computing, la computación distribuida, redes p2p, no sería descabellado dedicar ciertos esfuerzos a romper esas contraseñas si la información reservada que hay detrás puede suponer mucho, mucho, mucho dinero.

Tras tener todo esto en cuenta decidí que si la información que guardo detrás del formulario de nombre de usuario y contraseña por método post fuese lo suficientemente sensible y crítica, la guardaría en un entorno seguro https, pero como no es así no voy a hacer nada.

Además, quién va a querer perder el tiempo para obtener esa información y qué le va a aportar?

Nadie y nada.

Un saludo,

2 comentarios:

  1. Hola DomK, me alegro mucho de volver a verte por el blog. Hace mucho que no nos sorprendías con tus sesudas cavilaciones. Un abrazo, campeón.

    Paco.

    ResponderEliminar
  2. Hola DomK, disculpa la molestia y que te escriba en este post antiguo, pero queria saber si me podes facilitar el Plugin vPost de Velneo, te pido esto por que velneo ya no ofrece este servicio desde el 2010 y me comprometi con un Proyecto y no sabia que velneo tenia estas limitaciones y necesitaba de vPost para muchos campos en un Form web.
    Desde ya agradezco tu buena voluntad.
    Un Abrazo

    ResponderEliminar