arrow_back Volver
Inicio keyboard_arrow_right Artículos keyboard_arrow_right Artículo

Seguridad para aplicaciones web 101

Uriel Hernández

CTO de Código Facilito

av_timer 5 Min. de lectura

remove_red_eye 27668 visitas

calendar_today 05 Junio 2015

Para aclarar, si te estás preguntando qué significa el 101, significa que es lo más básico, normalmente los cursos de introducción en una universidad están acompañados del 101; para este artículo eso quiere decir que el 101 significa que hablo de lo más básico en términos de cómo mantener segura tu aplicación web.

Hace casi 4 años programé mi primera aplicación dinámica, era con PHP y mySQL, fue el resultado de leer un libro que pedí prestado en la biblioteca, era para que mis compañeros y yo pudiéramos subir nuestras tareas y el profesor las viera... fue un desastre. Al final terminó siendo inusable porque yo no sabía nada de lo que te voy a hablar ahora, en términos generales, las contraseñas de mis compañeros terminaron en una nota en internet, inyectaron javaScript en la página y me tomó horas darme cuenta, en fin.

Las contraseñas no se guardan en texto plano

Básico, nunca jamás debes guardar las contraseñas de un usuario en texto plano; las contraseñas se guardan encriptadas a una sola vía, es decir, a manera que no se pueda regresar al resultado original, cuando cursé Seguridad Informática en la universidad, mi maestro lo colocó de la siguiente manera

Si les digo que el resultado de una multiplicación es 30, ¿pueden decirme cuál era la operación original? 
La respuesta es: No, podría ser 15x2 10x3 30x1, etc, etc

Así funciona la forma en cómo se guardan las contraseñas, a través de una función de encriptación (MD5, Bcrypt) se generá un hash de la contraseña, este hash es el 30 en el ejemplo anterior, es el resultado de la operación, ese hash es lo que guardas en la Base de Datos, la clave aquí es que siempre que pases la contraseña por la función de encriptación, siempre va a retornar el mismo hash, SIEMPRE, por el contrario, no puedes regresar del hash a la contraseña original, tal como no puedes regresar de un resultado 30 a la operación original.

El flujo de login cuando la contraseña está encriptada se ve así:

  • Recibir la contraseña del formulario
  • Pasarla por la función de encriptación
  • Comparar el hash, resultado de la función de encriptación, con el texto de la base de datos
  • Si coinciden, la contraseña es correcta, si no, no lo es.

Lo importante aquí es que si por alguna razón alguien accede a tu base de datos, la roba, o algo así, igual no tendrá las contraseñas, sólo las versiones encriptadas. Nadie jamás nunca guarda las contraseñas en texto plano, ¿te has preguntado por qué cuando tratas de recuperar contraseña en alguna plataforma te mandan un link para reiniciarla en lugar de la contraseña antigua? La razón es que ni ellos saben la contraseña porque está encriptada :)

Limpia los datos que mandas en un query a la base de datos

Uno de los ataques más viejos en el desarrollo web es que te inyecten SQL, no voy a adentrarme mucho en eso porque es un tema por sí solo, pero lo que te puedo decir es que cualquier aplicación que no sanitiza los parámetros que recibe de un formulario antes de meterlos en un query de la base de datos es vulnerable a un ataque de inyección de SQL.

La mayoría de los frameworks modernos, si no es que todos, cuentan con protección a inyección de SQL, no está mal optar por un framework, no es pecado que no codees todo desde 0, si no quieres profundizar en esto, utiliza un framework, hay muchos muy ligeros como Flask para Python, Sinatra para Ruby, Lum para PHP (o CodeIgniter) y así.

Si no quieres usar un framework, todo está al alcance de una búsqueda en Google, por ejemplo aquí explican cómo limpiar parámetros en PHP, y lo único que hice para encontrar eso es buscar en google how to sanitize params in php. Ahora sustituye el PHP con la tecnología que quieras.

Limpia lo que imprimes

Uno de los ataques más populares en web es un ataque XSS básicamente es inyectar código del cliente en una aplicación web, por ejemplo, podría yo sustituir mi nombre de usuario por

<script>alert("Hola mundo");</script>

Y cada que vieran mi usuario en alguna parte de la plataforma, se imprimiría un alert en la pantalla, es un ejemplo básico y sin sentido, pero existen formas más complejas de vulnerar una aplicación con ataques XSS.

La mayoría de los frameworks de backend modernos no te dejan imprimir HTML como HTML, lo imprimen como si fueran una cadena, así que no hay peligro, sin embargo, habrá ocasiones en lo que necesitas es imprimir HTML de la base de datos y ahí es donde viene el problema.

Tenemos un ejemplo claro y en vídeo en el curso de Ruby on Rails 4, puedes verlo aquí no necesitas saber ni querer aprender Ruby, pero ahí se ve el ataque y cómo solucionarlo en Rails, si lo tuyo es PHP aquí encontré algo buscando how to sanitize html in php.

Captchas

SPAM SPAM SPAM SPAM, una de las peores cosas que te puede pasar es que te SPAMEEN la aplicación web, te llenan de basura la base de datos, ya alguna vez me pasó que me limitaron el uso de una API externa porque mi aplicación no estaba bien protegida y a alguien le pareció gracioso spamear uno de mis formularios. La solución default para esto es utilizar algo como reCAPTCHA es de Google y es fácil de integrar en una aplicación.

Personalmente no soy muy fan de los captchas, siento que rompen la experiencia de usuario porque es un poco molesto tener que llenarlos, lo que hago yo es limitar las peticiones por IP, digamos que en un formulario 5 digo que una misma IP no puede mandar más de 5 peticiones por minuto o se bloquea, esto es un poco más complicado (aunque sigue siendo sencillo) si estás mega iniciando, te recomiendo ir por un captcha.

Una solución inteligente con un poco de javaScript es la que ofrece David Walsh en este artículo básicamente coloca un campo oculto en los formularios que se llena con javaScript, si ese campo no viene lleno al llegar al Backend, se ignora la petición, si viene lleno, se acepta. Esto funciona porque normalmente los ataques se hacen con scripts externos que obviamente no ejecutan javaScript. Tiene la ventaja de ser sencillo y claro, no interfiere con un usuario (a menos que el usuario tenga desactivado javaScript).

Conclusión

El mundo de la seguridad es súper interesante, es enorme y es un desafío de todos los días, lo único que sabemos a ciencia cierta en la seguridad informática es que ningún sistema es impenetrable, así que, claro que esto es la punta del iceberg, lo más básico, lo 101, hay mucho más en proteger tu aplicación, pero claro, cada cosa se va haciendo más compleja y requiere de más conocimiento.

En lo personal, estoy 100% a favor de que antes de usar un framework intentes hacer las cosas desde 0 para que aprendas cómo funcionan las cosas y no parezca que el framework usa magia oscura para funcionar; sin embargo, si estás por subir una aplicación a producción, o un cliente te está pagando... bueno, no es el momento para practicar y aprender, en esos caso creo que te serviría utilizar un framework como Rails, Laravel, Django, o alguno más ligero como Sinatra, Flask, Lum, CodeIgniter, etc.

¿Qué otra medida de seguridad básica conoces? Compártela con nosotros en los comentarios