viernes, mayo 21, 2010

Control de acceso web "Dinámica de Tecleo"

Hace mucho, mucho tiempo que no escribo en el blog porque he estado muy ocupado pero al fin tengo un rato, así que, manos a la obra.
El artículo va sobre la seguridad y el control de acceso a aplicaciones web y quiero exponer un trabajo de investigación que realicé para un postgrado de la UNED, el control de acceso a aplicaciones web utilizando la dinámica de tecleo.
Podéis descargar los códigos y el script de creación de base de datos aquí.

Antecedentes
A la hora de control el acceso a recursos compartidos, se utilizan tres técnicas distintas, basadas en tres premisas:
  • Algo que el usuario sabe: esta es la premisa para el 99% de sitios, el usuario conoce un login y un password. Lógicamente, si un atacante consigue obtener esa información podrá suplantar la identidad. Este es, por norma general, el método más inseguro puesto que existen numerosas técnicas para robar las claves y, además, los usuarios no suelen usar claves alfanuméricas complejas porque son difíciles de recordar.
  • Algo que el usuario tiene: esta es la segunda premisa en la que el usuario es poseedor de algo que solo tiene él. Los sistemas que se basan en esto son los que utilizan tarjetas de coordenadas o certificados digitales, por ejemplo. Este sistema es más complicado porque se suele combinar con el primero y el atacante tiene que, o bien obtener una copia de lo que el usuario tiene o robárselo, además de obtener el usuario y la contraseña.
  • Algo que el usuario es: esta es la última premisa y es en la que se basa la seguridad biométrica. Las personas disponemos de rasgos o de actitudes que nos hacen únicos en el mundo. Usando esos rasgos físicos o esas actitudes o comportamientos que están impresos en nuestro cerebro se pueden generar patrones de seguridad que son mucho más complejos de romper que los dos anteriores. Usando este tipo de técnicas, el atacante, tendrá que copiar rasgos físicos (iris, retina, huella dactilar, forma de mano,...) o comportamientos (firma caligráfica, dinámica de tecleo,...) algo que en algunos casos es imposible y en otros en muy complicado.
Lo ideal es la utilización de forma combinada de las tres técnicas para obtener un sistema de acceso lo más seguro posible. En este artículo voy a exponer una forma práctica de implementar un sistema de control observando la forma de teclear de los usuarios (dinámica de tecleo) para determinar si el usuario ha sido suplantado o no.

Dinámica de Tecleo
La dinámica de tecleo es una técnica que se basa en el principio de que la acción de escribir en el teclado una palabra o frase (contraseña) muy frecuentemente hace que el acto de escribirla se convierta en algo inconsciente y automático. Esto provoca que ese gesto sea característico nuestro porque influyen tanto procesos mentales que se convierte en una especie de huella dactilar. Los parámetros que se tienen en cuenta a la hora de mesurar la dinámica de tecleo son dos, el tiempo de pulsación de cada tecla y el tiempo entre pulsaciones. En base a estos dos parámetros se pueden crear patrones de comportamiento que nos pueden decir si un usuario es o no es quién dice ser, independientemente de que la contraseña sea correcta o no.

Diseño del sistema de control de acceso
Lo que vamos a hacer es un sistema mixto de control. Por un lado, el usuario va a tener que introducir su usuario y contraseña, se validarán las credenciales y además se controlará la dinámica de tecleo de la contraseña. Dicho tecleo se comparará con un patrón del usuario para ver qué probabilidad hay de que sea realmente nuestro usuario y no un suplantador. Hay que tener en cuenta que cuando hablamos de biometría siempre consideramos probabilidades y no certezas. A la hora de configurar el sistema tendremos que elegir cuál es el umbral a partir del cuál consideraremos que el usuario es un suplantador. Cuanto mayor sea ese umbral, mayor será la seguridad pero más falsos negativos dará y cuanto menor sea el umbral, menor la seguridad pero menos falsos negativos. Cada uno modificará este umbral para que se adecue a sus necesidades y pruebas.

En nuestro sistema vamos a tener 3 módulos diferenciados:
  • Módulo de captura de datos: es el encargado de capturar los datos de pulsación y tiempo entre pulsaciones en el lado del cliente. Este módulo estará implementado en Javascript.
  • Módulo de entrenamiento: parte del sistema encargada de generar el patrón con el que se comparan las muestras a identificar.
  • Módulo de autenticación: parte encargada de decidir si un usuario es quién dice ser o no.
Generación del patrón
Lo primero es la generación del patrón para cada usuario. Tomemos por ejemplo, la palabra MANOLO, para la dinámica de tecleo tenemos que tomar las siguientes muestras:


Tomaremos una muestre para el tiempo de pulsación de cada letra y el tiempo entre pulsaciones. Para generar nuestro patrón tomaremos N muestras de la palabra clave MANOLO escritas por nuestro usuario, cada una de las muestras tendrá 2*n-1 posiciones siendo n el número de caracteres de la palabra. En este caso cada muestra o vector que guardamos tendrá 11 posiciones:

Una vez que disponemos de las muestras, tendremos que obtener un vector con las medias de cada posición y otro con las varianzas de cada posición.







El patrón del usuario será, por lo tanto, un vector de 11 posiciones con la media de cada uno de los tiempos de pulsación y tiempo entre pulsaciones y otro con un vector de 11 posiciones con las varianzas de cada uno de los tiempos. Este patrón lo almacenaremos en una base de datos para, posteriormente, poder realizar la comparación en el control de acceso.

Función de Scoring
La función de Scoring es la encargada de determinar el grado de similitud entre la clave introducida por el usuario que se quiere autenticar y el patrón almacenado en la base de datos.

Una vez obtenido el vector de valores SCORE, realizamos una media entre ellos para obtener un solo valor a comparar:

Este valor se comparará con el valor de UMBRAL definido en el sistema y determinará si el usuario es o no es quién dice ser.

Diseño Real del Sistema
Vamos a ver cómo, podemos diseñar en la vida real un sistema de control de acceso de este tipo. El flujo del sistema es el siguiente:


Para la implementación del sistema vamos a utilizar ASP.net (c#) como lenguaje de servidor, SQL Server como gestor de base de datos y Javascript para el control del tecleo.

Modelo de Base de Datos
En nuestro sistema vamos a tener dos tablas, una para la información de las claves del usuario y otra para almacenar los patrones:

Interfaz Web
Para nuestro ejemplo, se ha unificado en una sola interfaz el entrenamiento del sistema junto con el acceso al mismo:


El usuario tendrá que introducir su usuario y contraseña y, además, la frase de control que se ha utilizado para generar el patrón. En la parte de entrenamiento, el usuario puede ir introduciendo nuevas muestras, cuantas más muestras se tengan mayor será el acierto del sistema.

Cuando se pulsa sobre el botón "Acceder", el sistema devuelve en una pantalla tres valores:

  • Score Total: valor devuelto por la función de Scoring teniendo en cuenta tanto el tiempo de pulsación como el tiempo entre pulsaciones.
  • Score Pulsación: valor teniendo en cuenta solamente el tiempo de pulsación.
  • Score Entre: valor teniendo en cuenta solamente el tiempo entre pulsaciones.
Lógica del Cliente
En el lado del cliente, se ejecuta la lógica necesaria para capturar los datos de las muestras y enviarlos al servidor. Estas funciones se encuentran en Javascript (ver los códigos del proyecto) y preparadas para los exploradores más utilizados. El flujo de llamadas es el siguiente:


Para el caso de la comprobación del acceso al sistema, las llamadas Javascript son las siguientes:


Lógica del Servidor
Toda la lógica de la generación del patrón, la comprobación del usuario y la generación de la función de Scoring se realiza en el servidor. La comunicación entre el cliente y el servidor se realiza mediante llamadas a un servicio web llamado DinamicaTecleo.asmx ell cuál dispone de dos métodos públicos: RecibirMuestras y ComprobarAcceso.

El método RecibirMuestras es el encargado de recibir las muestras, formatearlas y guardarlas en base de datos:

El método ComprobarAcceso es el encargado de comprobar que el usuario es quien dice ser o no. Este método devuelve los tres valores que se muestran por pantalla:


Los datos del patrón se almacenan en la base de datos de la siguiente manera:



Se guardan las muestras de entrenamiento para cada usuario separadas por comas, en una columna los milisegundos de pulsación de cada tecla y en la otra los milisegundos entre pulsaciones.

Conclusión
Las conclusiones que se obtuvieron con los individuos que realizaron las pruebas fueron que, efectivamente, la dinámica de tecleo es una buena técnica complementaria al control mediante usuario y contraseña. Para que el sistema sea efectivo, la fase de entrenamiento debe ser extensa para disponer de muchas muestras. También es bueno eliminar aquellas muestras muy alejadas de la media.
El sistema funciona de forma óptima cuando la frase de control se compone de letras y números sin sentido puesto que es cuando el cerebro tiene que pensar qué teclas pulsar y tiene que mover las manos de su posición natural. En el caso de frases con sentido es más fácil la suplantación porque la posición de las manos y la cadencia es más natural.

Un fallo que no pude resolver en el sistema se produce cuando el usuario escribe tan rápido que antes de soltar una de las teclas ya ha pulsado la siguiente, generando un tiempo de pulsación negativo. Mediante javascript no fui capaz de controlar ese caso y obtenía un error. Si alguien lo corrige le agradecería que lo comentara.

En fin, creo que la dinámica de tecleo es un sistema fácil y barato de control biométrico, no necesitamos aparatos externos ni inversiones en dinero. Puede introducirse de forma transparente en un sistema ya establecido y puede aumentar el nivel de seguridad exponencialmente.

Espero que os haya gustado este artículo.


sábado, agosto 22, 2009

twitter desde línea de comandos

Twitter, ese gran amigo de muchos y mal endémico de la web 2.0 al que yo aún no había sucumbido. El enjuto hermano bastardo del "blogger". La forma de que la web 2.0 convierta tu vida en Tu Vida 2.0, aquí en Mundo Real™.

¿Y qué es lo que le preocupa a un usuario de GNU/Linux cuando conoce Twitter? ¿me quedaré enganchado a ésto por el resto de mis días? ¿seré hallado con 80 años muerto relatando mi propia agonía en 140 caracteres? ...

... pues no ...

... la verdadera pregunta es ... ¿se podrá hacer ésto desde línea de comandos? Y obviamente hay como otras 8000 personas a las que eso ya se les ocurrió antes, así que la respuesta a vuestras plegarias sale con un googleo simple.

Esta es una entrada chorra (tengo algunas más interesantes en mente y proyecto), así que sólo pondré las 2 formas que me han resultado más divertidas.


Fórmula 1 -- postear en twitter usando curl

Gracias al API de twitter, se puede usar curl para hacer un sencillo micro-post con un comando tan chorra como...

curl -u usuario:contraseña -d status="Tu mensaje" http://twitter.com/statuses/update.xml



Fórmula 2 -- Twitter Tools

Esta aplicación escrita en python es la que más me ha gustado para esta tarea (sólo he inspeccionado 4 o 5, tampoco es que tenga mucho criterio). Es sencillita y te permite ver tu twitter con sólo hacer...

twitter

¿Fácil no? Veamos 2 formas de instalarla.

La primera es la más sencilla, y consiste en instalar el paquete apropiado desde línea de comandos. Algo tan fácil como...

sudo aptitude install python-twitter

La otra forma consiste en irse a la página web (http://mike.verdone.ca/twitter/) y descargarse el código fuente (en tar.gz). Luego lo descomprimimos con...

tar -xvzf twitter-.tar.gz

ahora nos intalamos el paquete python-setuptools con...

sudo aptitude install python-setuptools

accedemos a la carpeta twitter dentro de la carpeta descomprimida y desde dentro hacemos...

sudo easy_install twitter

La ventaja de usar la versión descargada es que como es lógico, te descargas la última versión disponible que siempre va a estar por encima de la disponible en los repositorios. La desventaja, que no tienes la actualización automática que te dan los repositorios. Para algo con tan poco calado e importancia, yo personalmente recomiendo usar la instalación desde los repositorios.


La configuración

Para ahorrarnos el tener que poner el usuario y contraseña cada vez que vamos a consultar o escribir en nuestro twitter, podemos crear un fichero en ~/.twitter que tenga un contenido como el siguiente...

[twitter]
email: mi_usuario
password: mi_clave
format: ansi
prompt: '[cyan]twitter[R]'

...que hará que no tengáis que introducir usuario y clave, y además pondrá de colorines el resultado de las lecturas de forma que será más entretenido de leer :).


El resultado

Y ahora el resultado. Un ejemplo...

twitter set "Python Twitter Tools mola, lo recomiendo realmente a todos/as"
produciría un resultado que podríamos ver desde línea de comandos con el comando "twitter" como os pongo a continuación...



Y visto desde la web de twitter...


Y bueno, para quienes finalmente decidáis usar este sistema de microblogging ya iréis descubriendo que desde la Ptt (Python twitter tools) se pueden hacer muchas más cosas. Pero eso ya os lo dejo a vosotros/as.

Un abrazo a todos/as.

lunes, agosto 10, 2009

Códigos del motor de informes dinámicos en PDF

Debido a la demanda de los códigos, he realizado un pequeño proyecto sobre la entrada "Motor de informes dinámicos con iTextSharp(I)" . Os recomiendo leer primero el post para poder entender los códigos correctamente y sacarles el máximo partido.

Podéis descargar el proyecto desde aquí. Espero que os sea de utilidad.

sábado, junio 27, 2009

Sistema de plugins en C# usando Reflexión

En este post os voy a describir un pequeño sistema de plugins que implementé para un proyecto y que me resultó de mucha utilidad y sobre todo, me permitió aumentar el sistema sin tener que cambiar nada de lo ya establecido (códigos, recompilaciones, etc.).

La idea es disponer de un sistema de plugins para un CMS (gestor de contenidos) de forma que cada plugin sea autogestionado y no haya que tocar nada del sistema a la hora de introducir un nuevo plugin, salvo lógicamente introducir su definición en base de datos. En el proyecto que implementé, los plugins eran elementos visuales que permitían realizar la maquetación de las páginas mostrando el contenido de base de datos de diferentes formas (contenido tabulado, histórico, contenido con scroll, publicidad, etc.).



No voy a entrar en cómo implementar toda la estructura del sistema de elementos visuales (será para un artículo posterior), lo importante es cómo podemos, acceder a clases de c# sin utilizar elementos tipados. Es decir, lo normal para instanciar un objeto es utilizar la siguiente nomenclatura:

TipoObjeto miObjeto = new TipoObjeto(parametros);

En el caso de un sistema dinámico de plugins, no podemos utilizar esa nomenclatura porque no sabemos a priori la clase del objeto a utilizar. En esta situación, la reflexión se nos ofrece como técnica perfecta.

Implementación del sistema de plugins

Los plugins se dan de alta en base de datos, cada proyecto puede utilizar su propia definición de tablas. En mi caso, creé dos tablas, una para guardar la definición del elemento y otra para almacenar las propiedades modificables del elemento. Por ejemplo, uno de los plugins era para introducir un bloque de código HTML directamente en la página. La definición de este elemento es:


y la definición de sus propiedades es:


Lo importante de los datos almacenados para cada elemento es el campo "clase" en el que se guarda la clase de código que implementa la funcionalidad de este elemento. En este caso, la clase es plugins.elementoHtml. Este campo se utiliza luego para la reflexión.

Interfaz de los plugins
Este paso no es necesario pero es bueno que todas las clases que se encarguen de plugin implementen una interfaz obligando a que el método público de acceso sea siempre igual y no haya fallos de parámetros. En mi caso, la interfaz definía los siguientes métodos:

La interfaz define dos métodos, uno para obtener el código html del plugin cuando se debe insertar en el centro de la página y otro para cuando se debe insertar en el lateral de la página. Los parámetros que se pasan son el id particular para cada elemento y un object extras con parámetros extras que hicieran falta en cada caso.

El quid de la cuestión

En cada proyecto, obtendremos referencias a nuestros plugins de la manera que queramos. El quid de la cuestión se encuentra en las líneas que utilizan la reflexión para acceder a los métodos de la clase de cada plugin:




Lo que hacemos es:
  1. Obtener el campo "clase" de la base de datos y llamar al método Type.GetType para obtener el tipo del elemento.
  2. A través de reflexión podemos obtener acceso al constructor e invocarlo pasándole los argumentos necesarios, en este caso null porque no hay argumentos.
  3. Obtener la información del método "Renderizar" que es el que utilizamos de cada clase y que define la interfaz.
  4. Invocamos el método pasándole el objeto inicializado mediante el constructor y le pasamos un vector de objects con los parámetros que el método está esperando.
  5. El resultado del método (en este caso un string), se obtiene haciendo un cast a string.
Conclusión
La reflexión es una herramienta muy potente dentro del lenguaje .net que permite llamar a métodos y objetos sin conocer previamente el tipo. Esto permite generar sistemas como el descrito de una forma eficiente. El problema estriba en que, inicialmente no es un tipo de programación sencilla y requiere un tiempo para acostumbrarse a cómo funciona.

Espero que os haya gustado este artículo y que os sirva esta idea para vuestros desarrollos. En mi caso, me ha sido de mucha utilidad.




domingo, junio 14, 2009

Problema de expiración de la sesión en ASP.net

Los códigos de este post los podéis descargar desde aquí

Finalmente, por fin he encontrado un rato para escribir un post en el blog. Tenía en mente varios temas pero al fin me he decidido por éste que me parece bastante interesante y útil para aquellos que desarollamos aplicaciones en asp.net. Pongámonos en situación, cuando escribimos aplicaciones, una de las herramientas más utilizadas para mantener la persistencia de los datos es la sesión, almacenamos en sesión tablas con las que trabaja el usuario por pantalla, ids de filas, usuarios, variables, etc. todo ello para que cuando el usuario pulse algún botón y se realice un postback, podamos realizar las acciones correspondientes. Es decir, la sesión nos mantiene conectado con el usuario en un entorno desconectado. El problema viene cuando el tiempo de sesión expira, si el usuario no ha realizado ninguna acción pasados x minutos (5 por defecto), el servidor (IIS) elimina su sesión. En el momento en que el usuario pulse un botón y se vaya al servidor, nos encontraremos con que aquellos datos que habíamos guardado en la sesión ya no existen y (dependiendo de cómo controlemos esta situación) saltará una excepción en algún punto de nuestro código, echándonos fuera de la aplicación, o saltando una fantástica pantalla amarilla o algo parecido.

En aplicaciones en las que las operaciones se realicen en el servidor no vamos a tener problemas con la sesión porque cada vez que el usuario realice un postback, la cuenta de expiración de la sesión se reinicirá. En el caso que hagamos aplicaciones que hagan uso de la lógica del cliente, tipo blogs, editores wysiwyg, o que el usuario realice operaciones largas en el explorador sin tener que ir al servidor, el tiempo de expiración de la sesión se convierte en un gran problema para el programador y en una gran molestia para el cliente. Imaginaos escribiendo un post en un blog y que cuando lleváis 30 minutos escribiendo, habéis acabado el post le dais a guardar y salta una excepción, perdiendo todo el trabajo...

Posibles soluciones a este problema
Existen varias soluciones a este problema, que dependiendo de dónde esté alojada nuestra aplicación nos serán factibles o no.

Solución 1: Web.config

La solución más fácil es incorporar en nuestro web.config la etiqueta "sessionState" con el atributo "timeout" indicándole el número de minutos que deseamos que se mantenga la sesión (dentro de la sección system.web):



En este caso, hemos aumentado el tiempo de sesión a 60 minutos, antes de que el servidor la elimine. Sin embargo, me he encontrado alojamientos en los que, aunque en mi web.config tenga incluido este tag, el tiempo de sesión viene marcado por el servidor sin posibilidad de cambiarlo desde aquí.

Solución 2: Pool de aplicaciones
La segunda solución con la que contamos es la de crear un pool de aplicaciones en el IIS para nuestra aplicación. En dicho pool podemos especificarle el tiempo de sesión que queremos. Además, al crear un pool propio, se lanza un proceso en el sistema para nosotros solos. Esto es bueno en el caso de alojamientos compartidos en los que en el mismo proceso puede haber muchas aplicaciones ejecutándose. Siempre es aconsejable tener nuestro propio pool de aplicaciones, el cual se crea de la siguiente manera:

1. Desde el administrador de IIS, pulsamos con el botón derecho sobre "Grupos de aplicaciones" y seleccionamos un nuevo grupo:


2. Le damos un nombre al nuevo grupo de aplicaciones:


3. Lo siguiente es configurar las opciones de rendimiento para este grupo de aplicaciones, como la cantidad de memoria a asignar, el tiempo de reciclado del proceso o el tiempo de sesión para este grupo, entre otras opciones:


4. Por último, a un sitio o directorio web, le asignaremos este grupo de aplicaciones desde sus propiedades:


Solución 3: Servicio web de Echo
Para implementar las dos soluciones anteriores necesitamos tener control sobre el servidor (cosa que no siempre es así). En el caso que tengamos alojamientos compartidos, podemos utilizar esta opción (es la que utilizo ahora). Normalmente, un portal web dispone de dos partes, la pública (en la que normalmente se puede funcionar con cookies) y la privada en la que trabajaremos con sesiones. Es en la parte privada donde utilizaremos esta opción. La idea es implementar un servicio web que simplemente realice un eco, reciba un parámetro y lo devuelva. Habilitamos la sesión para el servicio web con lo que cada vez que se llame a este servicio, la cuenta de expiración de la sesión se reinicirá. Desde las página de gestión se llama, vía AJAX, periódicamente (yo lo tengo cada 50 segundos) a dicho servicio web para que no reinicie la cuenta. De forma esquemática, la solución es la siguiente:


El código del servicio web es el siguiente:

Tenemos que introducir el using System.Web.Script.Services para poder utilizar este servicio web vía AJAX. Además, la definición del servicio web incluye la sentencia [WebMethod(true)] indicando que se utilizará la sesión en ese método del servicio web. Para llamar a dicho método desde la página maestra (lo normal) o desde cualquier página de nuestra aplicación utilizaremos el siguiente código:

a. Incluir una referencia web al servicio web creado.
b. Dar de alta el servicio web mediante el ScriptManager de la página
En la propiedad Path pondremos la ubicación del fichero .asmx (servicio web). Si, al crear el servicio web, separados el código del fichero, se creará un fichero .asmx con la definición del servicio web donde le hayamos dicho y un fichero .cs con los códigos dentro de la carpeta App_Code.


c. Crear la función Javascript que llama al servicio web


d. Crear el temporizador para que se repita la llamada cada x segundos

Ponemos la función en el onload de la página para que se ejecute al iniciar la página. En este caso esta puesto que se repita la llamada cada 50 segundos (50.000 milisegundos)


Conclusión
Esta última es una solución sencilla que nos puede servir en cualquier entorno en el que trabajemos con aplicaciones asp.net. Utilizando el servicio de echo, nos aseguramos que la sesión del usuario no va a expirar independientemente del tiempo que esté sin hacer ningún postback. En el caso que el usuario cierre la ventana del explorador, se deja de llamar al servicio con lo que la sesión expirará en los 5 minutos correspondientes. Por supuesto, siempre podemos colocar el botón de cerrar que matará la sesión. Como siempre, espero que os sea de utilidad este post y gracias por leer este blog (ya sois un montón).