Nota del autor

Si la entrada que estás leyendo carece de imágenes, no se ve el vídeo que teóricamente lleva incrustado o el código fuente mostrado aparece sin formato, podéis conocer los motivos aquí. Poco a poco iré restableciendo la normalidad en el blog.
Este blog es un archivo de los artículos situados previamente en Lobosoft.es y ha dejado de ser actualizado. Las nuevas entradas pueden encontrarse en www.lobosoft.es. Un saludo,
Lobosoft.

domingo, 28 de septiembre de 2008

Protección ante XSRF

Que la seguridad en las aplicaciones web debería ser un objetivo prioritario es algo que, a día de hoy, no puede resultar ajeno para nadie. Pero es habitual encontrar multitud de vulnerabilidades en el código de este tipo de aplicaciones que permanecen expuestas a millones de usuarios potenciales, y si entendemos a éstos como personas (otro caso será el de sistemas que actúen como usuarios de nuestros servicios) nos encontramos hablando de dos escenarios bien diferenciados pero complementarios: de un posible atacante y del usuario como eslabón más débil de la cadena.


Hoy quería traer al blog una pequeña introducción sobre XSRF (también conocido como CSRF o Cross Site Rereference Forgery), un modo de ataque basado en lo predecible de las invocaciones entre elementos en la Web y en la forma en que es procesada la información en los navegadores. XSRF actúa justo desde la perspectiva opuesta a los ataques XSS. Aquí es el sitio web “confiado” el que puede ser atacado con facilidad, ya que XSRF realiza una determinada petición a un sitio web que, si no es controlada por éste, puede desembocar en una actualización en la BD, la desconexión del usuario o llevar a cabo cualquier otro tipo de acción. La forma de conseguir que se ejecute la acción que pretende llevar a cabo el atacante es tan sencilla como incluir un determinado código aparentemente inocente en el servidor (mediante un ataque XSS, por ejemplo), o consiguiendo mediante ingeniería social que la víctima visite un sitio web del atacante que ejecutará automáticamente la acción.


Imaginemos que deseamos desconectar a nuestra víctima de un servicio, pongamos un ejemplo (y no quiero mirar a nadie…), de su cuenta de Google. Por poder, podemos hasta elegir la manera en que hacerlo: incluyendo una imagen rota/oculta, mediante un tag script, utilizando iframes o mediante un formulario (con peticiones tanto GET como POST). Para conseguir que se ejecute la acción, podemos enviar a la víctima un correo electrónico con una imagen incrustada, invitarle a visitar la presentación de un nuevo servicio, etc.


En el sitio web, que no requerirá de más tecnología que del HTML, podemos tener una página que incluya código como el siguiente (a elegir):




  • Un iframe con el src establecido a la URL de la acción a ejecutar:
    http://mivictima.com/logout

  • Un script:


  • Una simple imagen:

  • Un formulario:




  • Otro script:

    var img = new Image();
    img.src = " http://mivictima.com/logout ";




Todas estas técnicas funcionarán en webs que acepten parámetros mediante GET, siendo posible el ataque mediante POST utilizando el formulario (que, además, puede ser “lanzado” automáticamente mediante la inclusión del parámetro
OnLoad=”document.getElementById(miform).submit()”
en la etiqueta BODY de la web) o a través del último script presentado.


Como vemos resulta ser un método bueno, bonito y barato. Su potencial es mucho más alto, y podéis encontrar más información en el documento de Information Security Partners, o descargando los ejemplos de la entrada.


Visto esto, ¿cómo podemos proteger nuestro sitio web ASP.NET de este tipo de ataques? (Lo que veremos ahora, salvo excepciones, es válido para otro tipo de tecnologías, con ligeros cambios).




  • Evitar recuperar parámetros de la URL:
    Utilizar formularios que pasen los parámetros mediante POST. En ASP.NET deberíamos recuperarlos usando HTTPRequest.Form (Request.Form) en lugar del más común Request.Params["miparametro"];


  • Utilizar tokens de identificación:
    Es posible utilizar elementos que identifiquen a nuestro usuario, de manera que si la petición llega al servidor sin incluir dicho token (almacenado, por ejemplo, en sesión), no se llevará a cabo la acción solicitada. Incluso es posible asignar dicho token al par (usuario/acción), almacenando dicho token en nuestro servidor para mejorar incluso la seguridad del sitio web en lo concerniente a la autorización del uso de recursos. Lo ideal es que este token viaje entre el equipo del cliente y nuestro servidor vía POST, para que no sea visible en la URL (aunque podría viajar cifrado –y aquí poder es deber ;) -) y no llegue a otros sitios web a través del HTTP_REFERER.
    El uso de POST no nos inmuniza ante el XSRF, pero podríamos considerarla como una buena práctica de programación desde el punto de vista de la seguridad de nuestro código.
    También podemos utilizar el ViewState, utilizando la propiedad Page.ViewStateUserKey que proporciona un identificador único para el usuario que está visitando una página en concreto. La asignación de la propiedad se lleva a cabo durante el proceso de carga de la página, en concreto en el Page_Init de la misma.
    [csharp]void Page_Init(object sender, EventArgs e)
    {
    ViewStateUserKey = Session.SessionID;
    }[/csharp]

    La única pega de esta protección es el modo en que se comprueba el ViewState de la página, dependiendo de que exista un PostBack de la misma, por lo que no sería de mucha utilidad en aplicaciones que no lleven a cabo esta acción con frecuencia, como es el caso de las RIA’s que hacen uso intensivo de AJAX.


  • Limitar la duración de las sesiones de usuario:
    Si usamos la generación de un identificador único por usuario, podemos “forzar” la generación de más identificadores reduciendo (en un margen conveniente pero racional) la duración de la sesión en nuestro sitio web. Con esta acción únicamente ganamos algo de seguridad al reducir la ventana de exposición de los identificadores. Como contrapartida, algunas aplicaciones necesitan sesiones prolongadas, por lo que no sería factible llevarla a cabo en esos casos.


  • Controlar el HTTP_REFERER:
    Permitir únicamente solicitudes que provengan de nuestro dominio. Evitaremos así un posible ataque XSRF desde el exterior, aunque no nos protege de nosotros mismos: si un usuario es capaz de inyectar HTML en algún formulario que provoque la ejecución de la acción (y aquí uno de los mayores riesgos es la posibilidad de utilizar la etiqueta ), o sufrimos un ataque XSS de cualquier tipo, nuestra web estará expuesta también a XSRF.
    Al igual que el uso de POST, el control del HTTP_REFERER tampoco nos inmuniza frente al ataque de sitios ajenos a nuestro dominio, ya que el HTTP_REFERER puede ser simulado utilizando XmlHttpRequest o Flash, pero nos proporciona un poco más de seguridad que si no lo tenemos en cuenta, claro está.


  • Enviar una doble cookie:
    El XSRF se basa, como apuntaba al principio, en la posible ejecución de una acción en nuestra web desde un lugar (o dominio) ajeno a nosotros. Sin embargo, por la propia filosofía con la que se construyen los navegadores, las cookies pertenecientes a un dominio no pueden ser consultadas por otro. Por esto, podemos enviar el contenido de una cookie normalmente (usando la cabecera de la página) y otra vez como un valor oculto en un formulario, (leyendo la cookie mediante JavaScript e insertándola en el mismo). Si las dos cookies que nos llegan de este modo no coinciden, deberíamos ir planteándonos rechazar la petición ;) . La desventaja de este método es que no funcionaría en caso de que el usuario deshabilitase la ejecución de JavaScript en su navegador.

Para terminar, únicamente me gustaría insistir en la necesidad de formar a nuestro equipo de desarrolladores en metodologías adecuadas para lograr alcanzar un buen nivel de seguridad en nuestras aplicaciones. Esto es particularmente importante en aplicaciones web, que ya sea desde Internet o dentro de una Intranet, están expuestas a un gran número de posibles ataques. La seguridad, en programación, debería ser parte del diseño y no “algo” que implementar sobre la marcha, si hay tiempo…


Para saber más:


2 comentarios:

  1. Información Bitacoras.com...

    Si lo deseas, puedes hacer click para valorar este post en Bitacoras.com. Gracias....

    ResponderEliminar
  2. Buenos dias, me ha parecido muy interesante e ilustrativo, gracias por compartir tus conocimientos con la comunidad.

    ResponderEliminar