Cómo securizar una web y que se te vaya la pinza en el proceso

¡Hola a todos!

Estos días ando desarrollando una cms llamada “DiceSystem” la cual está orientada al mundo de los juegos de rol en vivo. Esta cms permite registrarse y seleccionar un personaje, solicitar su ficha, comunicarse con los masters, etc…

Además, permite a los administradores gestionar la “web” del juego. Es decir, los textos e imágenes de la frontpage (que será lo que vean los que no estén registrados). Y, claro, cuando haces un sistema que permite a desconocidos introducir datos que van a una base de datos es cuando empiezan los problemas reales.

Repasemos los problemas más comunes (que yo conozco):
-Que te inyecten código en el login para entrar en alguna cuenta.
-Que modifiquen las cookies para que el sistema piense que es otra persona.
-Que empleen cualquier “introductor de valores” (textboxes, comboboxes, parámetros de la url, etc…) para inyectar código a ciegas y sacar la estructura de la bd junto con sus datos.

Nota: Si conocéis cualquier otro problema “común” dejádmelo en los comentarios, por favor.

Para estas cosas estoy tomando unas medidas que en algunos casos son un poco… paranoicas.

Login
El login es uno de los puntos más sensibles de una web, y por ello la primera que debemos securizar (aunque no la única). Por tanto, mi diseño de bd para esta cms consta de dos bd’s. La primera es un mysql con todos los datos de la web, usuarios, etc… a excepción de la contraseña y de la semilla de hasheo. Estos datos están en una segunda bd que, por cierto, es una sqlite por el tema de que muchos webmasters sólamente pueden tener una base de datos en su hosting. Concretamente lo que guardo en esta bd es la id del usuario (que corresponde con la id en la otra bd), el nombre de usuario pasado por md5 (luego explico para qué), la contraseña (hasheada con un algoritmo que luego os explico) y la semilla de dicho algoritmo.

Al introducir los datos de login, el sistema realiza las típicas funciones de htmlentities, mysql_real_escape_string, etc… Después, pasa por md5 el nombre de usuario y busca en la sqlite la línea que corresponda a este usuario. Al haber pasado por md5 la cadena de nombre de usuario, es imposible que haya una inyección de código, porque el resultado del hasheo es una cadena alfanumérica, que es lo que le paso a la bd.

Una vez recuperados los datos de este usuario, paso la contraseña introducida por las mismas funciones que antes, y posteriormente la paso por esta función (http://pastebin.com/qBVmjgCX). La semilla que requiere esta función, es la que hemos recuperado de la sqlite y se compone de una string de entre 0 y 120 caracteres que van del 0 al 9 (controla con un default cualquier otro valor).

Si la contraseña recuperada de la sqlite y esta que acabamos de tratar coinciden es que ha introducido la correcta, así que hacemos una breve comprobación en la base de datos normal para asegurarnos de que no está baneado y creamos la sesión. Por supuesto, el dato que introducimos en esta consulta es el id que hemos obtenido de la sqlite.

Control de sesiones
En el index del ucp y del acp, comprobamos que la variable de sesión contiene el id de un usuario existente en la base de datos y que no está baneado. Esto es importante, porque si alguien posee una sesión para un usuario que no existe (id!= a cualquier id de la tabla de usuarios) podría liarla bastante. Así que si ocurre alguno de estos dos casos, le mandamos para logout.php que destruirá su sesión.

Además, puesto que index.php es quien incluye todos los contenidos, si detecta que no existe una sesión, hará caso omiso de los parámetros de la url y traerá login.php.

El control de administración (ACP) comprueba además que el que accede tiene los privilegios adecuados.

Control de permisos
Enlazando con el punto anterior, en el ACP se dispone de dos niveles de privilegios: administrador y root. El administrador es cualquier usuario con privilegios de administración. Sólamente puede leer datos y gestionar a los usuarios y los personajes (tanto darlos de alta y baja, como añadir sus fichas y documentos adicionales).

Para modificar la información del vivo, los datos de conexión de la bd, otorgar privilegios de administración a usuarios, etc… hay que “solicitar” privilegios superiores. En líneas generales, es un botón que pone sudo y que al darle te pide un login en el que introduzcas tu usuario, tu contraseña y la contraseña de root (que es una cuenta con la que el sistema no te deja hacer login). Si todos los datos introducidos son correctos, se modifican las cookies del cliente para que el sistema detecte los nuevos privilegios.

Sin embargo, estas cookies modificadas tienen fecha de caducidad (una hora). Si el usuario pasa una hora sin realizar actividades, el sistema le denegará el acceso con privilegios de root y le restaurará sus privilegios.

Leave a Reply