Manual de Practicas de Seguridad de Aplicaciones Web

1. Prologo

El presente manual es una recopilación de algunas prácticas de Seguridad de Aplicaciones Web, que le ayudará a implementarlas en su sitio o aplicación. Esto no significa que si implementa todas estas prácticas su sitio está garantizado a recibir cualquier tipo de ataque, pero si estará más protegido que si no implementara ninguna práctica.

Recomiendo este manual a Programadores novatos y avanzados que estén desarrollando aplicación web, que estén en busca de una respuesta rápida y precisa de cómo proteger su sitio y cuáles son las formas de protegerse de ataques hostiles.

2. Evitar Inyección de código HTML o Javascript

Como programador de aplicación web muchas veces nos enfocamos a que nuestras aplicaciones funcionen correctamente, al menos en mi caso, pero ponemos poca importancia en la seguridad y hasta que no ocurre una intromisión es cuando nos ocupamos de conocer más acerca de la seguridad, y he decidido ordenar los temas en orden de nivel de seguridad, empezando con lo más básico, por lo que comenzaremos con la inyección de código html y javascript.

Como sabemos muchas veces realizamos formularios o aplicaciones que recibe datos, y por lo regular validamos desde javascript la entrada de datos como; email, números telefónicos, direcciones y demás, pero en ocasiones no sabemos la vulnerabilidad de estos formularios, ya que en estos si no se valida correctamente se puede insertar código html o javascript, que puede resultar en que nuestra sitio no funcione o que evite que funcione.

Algunas de las cosas que se pueden hacer con código html son:

· Insertar una imagen no deseada en un lugar no deseado.

· Redireccionar una página a otra sin tener autorización.

· Ciclar una página para con una sentencia javascript recursiva.

Y puedo continuar con la lista, todo dependerá de la maldad del saboteador, lo importante y en lo que nos enfocamos en este manual es en cómo evitarlo, por lo cual recomiendo lo siguiente.

En el caso de formularios que estén abierto al público y a usuarios registrados si es que tiene alguna especie de panel o intranet, deberá de limpiar todos los datos de tipo cadena y numéricos de todo código HTML, de acuerdo a cada lenguaje existen diferentes manera, por ejemplo en PHP la función htmlentities cambia todas las sentencias html para que no puedan ser ejecutadas cuando son mostradas, por ejemplo si usted quisiere insertar una sentencia para mostrar un imagen al limpiar el código en su base de datos se guardara así <img href="www.domiox.com" /> esto es inofensivo al momento de imprimir estos datos en el sitio, evitando así cualquier intento de inyección de Código HTML o Javascript, así que de acuerdo a cualquiera de los lenguaje en el que esté desarrollando busque una función para limpiar la entrada de datos.

3. Evitar Inyección de código SQL

Este punto es de mayor importancia porque si algún hacker encuentra una sola página con ésta vulnerabilidad puede tener acceso a toda su información y puede hacer bastante daño, por lo cual recomiendo implementar esta práctica en si sitio.

La inyección de código SQL funciona de manera muy similar a la inyección de código HTML, pero en este caso con código HTML. Como sabrá el estándar SQL tiene el poder de hacer muchas transacciones en su base de datos, desde consultar datos hasta crear usuarios, dependiendo del SMBD (Sistema Manejador de Base de Datos), en este caso vamos a utilizar ejemplos con el SMBD MySQL 5, pero igual y los otros como ORACLE, MS-SQL Server etc, funcionan de manera muy similar.

Lo que no debe de hacer.

La puerta de acceso puede ser cualquier página de su sitio que esté abierta al público en general, por ejemplo en un sitio de noticia, que por lo regular tiene una parte donde todo el mundo tiene acceso sin password es la parte más sensible y la que debe validar mucho más.

Como ejemplo voy a utilizar un sitio ficticio desarrollado en PHP y MySQL, por lo regular solemos usar variables GET para este tipo de sitios, y los link se parecen a esto:

http://www.sitionoticias.com/ver_noticia.php?id=11

Esto es lo que los usuarios novatos hacen por lo regular, dentro de su código tendría algo así:

“SELECT * FROM noticas WHERE id_noticias=” . $id ;

Esta es una puerta abierta, por que el hacker puede hacer esto:

http://www.sitionoticias.com/ver_noticia.php?id=11+or+1=1

Lo cual tendrá como resultado en si consulta

SELECT * FROM noticas WHERE id_noticias=11 or 1=1

Lo cual le dirá al hacker que usted no está encodillando su consulta, y a partir de allí podría insertar cualquier otra consulta sql, por ejemplo puede saber cómo se llaman sus tablas, hasta dar con la tabla de usuarios, y obtener cualquier usuario y password y si no lo tiene el password encriptado tendrá acceso ahora a todo el sistema, no vernos como se puede lograr esto por que no es el fin de este manual, pero le enseñaré como evitarlo.

Como evitarlo

Para evitarlo debe poner todo entre comillas, inclusive los campos numéricos, esto con el fin de que todo el código escrito sea interpretado como una cadena y no como una sentencia SQL.

Si tiene esta consulta:

“SELECT * FROM noticas WHERE id_noticias=” . $id ;

Debe escribirlo asi:

“SELECT * FROM noticas WHERE id_noticias= ’” . $id . “’” ;

En MySQL si usted pone un valor de tipo INT el MySQL lo convierte a númerico de manera automática, investigue si su SMBD lo acepta, lo cual debe hacerlo, no conozco todos los SMBD pero creo que deben de poder tener esta sintaxis.

Lo mismo debe hacer con las sentencias SELECT, INSERT y UPDATE porque también en estas se puede insertar código.

4. Evitar robo de contraseñas de usuario

En el peor de los casos si el hacker tiene acceso a su BD y quiere entrar a las cuentas de usuarios debe de ponerle el camino más difícil, porque nada es 100% seguro ni está exento de alguna falla en el código deberá de proteger sus password, por lo menos le dará tiempo de blindar mejor su sitio.

Por lo cual le recomendó encriptar sus password en su BD, en PHP puede hacerlo con una función aun que hay métodos más seguros que otros puede usar una encriptación básica, este simple paso puede ser la diferencia entre que puedan robar sus contraseñas o no.

5. Arquitectura de Privilegios de usuarios.

En muchas ocasiones los sistemas comienzan siendo pequeños sistemas, pero con el tiempo se convierten en grandes sistemas, que muchas veces por la mala planeación descuidamos puntos clave de seguridad.

Muchas arquitecturas de seguridad son como el siguiente:

Lo que no debe de hacer.

Tenemos una tabla con los usuarios, que por lo regular comienza siendo un solo tipo de usuario, el administrador, pero con el tiempo se necesitan más perfiles con diferentes privilegios.

Y lo que nuestra lógica nos dicta es utilizar sesiones, -Que en PHP es muy usado- , y nuestra manera de validar el acceso es mediante un menú, por ejemplo:

Tomando el mismo ejemplo del sitio de noticias tendríamos lo siguientes módulos:

· Usuarios

· Noticias

· Catálogos

· Anuncios

· Clientes

Lo que por lo regular llegamos a hacer los programadores novatos, es hacer una página que sólo muestre el menú con las opciones a las que se quiere que se tenga acceso, por ejemplo para el usuario de tipo administrador tendría acceso a todas las opciones, pero un usuario de tipo Noticas, el cual podría ser un empleado de la compañía o alguna persona externa a la compañía, podría tener sólo acceso a las noticias, o al menos eso creemos que va hacer, pero por azares del destino su cuenta cae en manos de un hacker, o simplemente deja abierta su sesión en un café internet y alguien tiene acceso a su cuenta, esto es una posibilidad remota, pero créanme ha sucedido, entonces que pasa aquí.

Como la arquitectura de seguridad utiliza una variable de sesión para validar si se tiene acceso o no pasaría lo siguiente, el código PHP de validación seria así:

session_start();

if( $_SESSION['intranet'] != 'acceso autorizado'){

header('Location: intranet.php');

}

Esto podría verse que es seguro, pero si está utilizando el mismo nombre de la sesión, en este caso $_SESSION['intranet'] para los dos o más tipos de ususario, un usuario de noticias podría tener acceso a las opciones del administrador, sólo tiene que saber la url de las páginas del administrador, esto lógicamente dependerá del tipo de programación utilizada pero el objetivo es que no cometa el error de usar una misma variable de sesión para varios tipos de usuarios, porque si entra para un tipo de usuario podrá entrar como los otros usuarios y realizar las operaciones con los privilegios de otros tipos de usuario como el administrador.

Como evitarlo

Si tiene varios perfiles de usuario debe utilizar otro método adicional para validar que el perfil puede hacer que operaciones, por lo cual debería tener algo así;

Una tabla con una lista de todas las operaciones que se pueden realizar, otra con los perfiles y otra con la relación entre el perfil y la operación.

Cada operación puede ser un programa o una función o una inserción de datos etc, eso dependerá del sistema, esta arquitectura es fácil de implementar sin hacer muchos cambios en su código.

6. Descarga de Archivos.

Los problemas de vulnerabilidad solemos insertarlos de manera inconsciente, con mis ya 5 años como programador les puedo decir que programamos para solucionar un problema no para proteger la información, esta es la manera de un programador promedio, por lo cual estamos en desventaja con los hacker, por solo piensan en como pueden atacar.

Esta vulnerabilidad es cuando se tienen que descargar un archivo de su servidor, muchas veces leemos que la forma de forzar una descarga de un archivo es utilizar algunas rutinas.

Lo que no debe de hacer.

Pasar como parámetro el nombre del archivo. Es decir digamos que tenemos un programa que se llama descargar.php donde le pasamos como parámetro --ya sea GET o POST—el nombre del archivo, y podemos decir que es correcto, pero que pasa si se suprime el nombre del archivo por otra ruta:

Lo usual seria esto: www.dominiox.com/descargar.php?archivo=archivo.xls

Si usted ha hecho esto es muy posible que todo su sitio esté en peligro, ya que el hacker puede hacer esto.

www.dominiox.com/descargar.php?archivo=../index.php

Lo cual descargaría el archivo original index.php, increíble pero cierto, yo cuando me entere de esto me quería tirar del segundo piso.

Esto significa que puede descargar cualquier archivo es decir el código fuente, lo demás lo dejo a su imaginación, que podemos hacer con el código fuente.

Como evitarlo

No utilice esta forma para descargar archivo, es mejor imprimir la url del archivo para que el usuario lo descargue desde una liga, no que lo pase como parámetro.

Recuerdo que el utilizar un parámetro POST no soluciona el problema porque se puede hacer una llamada POST desde otro servidor y mandar de igual manera el nombre de otro archivo.

Comentarios