Protección XSS en Django

3

Visto 3174 veces | Publicado el 07/10/2011 | www vulnerabilidades educativo


Django es un framework Web open source escrito en lenguaje Python que permite construir aplicaciones Web de forma más rápida y con menos líneas de código. La documentación de dicho framework se puede consultar y descargar en la siguiente página: https://www.djangoproject.com/ .

En este artículo, se van a explicar y detallar una serie de pruebas que se han realizado para analizar cómo Django trata los riesgos derivados de no filtrar y/o validar correctamente la entrada de usuarios en una página Web, centrándose en los riesgos de ataques de Cross-Site Scripting (XSS). Las pruebas realizadas consisten en crear en cualquier proyecto de Django (esto no es objeto del presente artículo) un template HTML llamado, por ejemplo, "poc.html" con un formulario como el siguiente y someterlo a ataques de XSS:

{% extends "base_site.html" %}

{% load i18n %}

{% block content %}

<div id="content-main">
{% trans 'Django Calendar XSS PoC' %}
<br><br>
<form method="post" action="{{action}}" >
<table border='1' cols='2' width='200'>
<tr><td colspan='1'><input type="text" name="desc"></td></tr>
<tr><td><input type='submit' value='Enviar'></td></tr>
</form>
</table>
<br><br>
<table border='1' cols='2' width='200'>
<tr><td colspan='1'>Desc vale: {{desc}} </td></tr>
</table>
</div>
{% endblock %}

El formulario anterior tendrá el siguiente aspecto, un formulario típico con un campo de texto para rellenar y un botón para enviar:

El código que trata esta petición, es decir el código que irá en el fichero views.py correspondiente a esta aplicación de Django, sólo recupera el contenido del POST, lo imprime por pantalla y lo envía al template para que se muestre.

Si se inserta en el formulario creado una sentencia típica de ataques de XSS (<script>alert('xss')</script>) el resultado es el siguiente:

En la consola se mostrará el valor de la variable "desc" enviada en el POST:

[26/Sep/2011 12:38:12] "POST /t/ HTTP/1.1" 200 1774
<script>alert('xss')</script>

Por pantalla se verá:


Es decir, en la consola se observa que la variable "desc" no está correctamente filtrada, el código que se ejecuta en la vista no modifica el contenido de esta variable "desc" pero, sin embargo, al mostrar el contenido de dicha variable en el HTML no se ha ejecutado el código JavaScript ya que los carácteres están convertidos a su correspondiente entidad HTML (http://www.w3schools.com/tags/ref_entities.asp).

Si se consulta el código html de la página se comprobará que efectivamente estos carácteres están convertidos a su correspondiente entidad HTML.


¿Qué sucede si se marca la variable "desc" como segura para el sistema de templates de Django?

Se modifica el template "poc.html" para incluir el filtro de Django (safe):

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#autoescape
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#safe

Se substituye en el formulario {{desc}} por {{desc|safe}}:

<tr><td colspan='1'>Desc vale: {{desc|safe}} </td></tr>

Al quitar el filtro que trata determinados carácteres (problemáticos para XSS) el resultado es:


¿Qué dice Django al respecto?

En la versión 1.0 se incluye por defecto para los templates "autoescape" que básicamente escapa todo el contenido de las variables antes de enviar el resultado a la salida.

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#autoescape

En versiones de Django anteriores a la 1.0 no existe esta caracteristica de "autoescape". Se puede consultar más información sobre todo lo anteriormente comentado aquí en:

https://docs.djangoproject.com/en/dev/topics/security/#cross-site-scripting-xss-protection
https://docs.djangoproject.com/en/dev/topics/templates/#automatic-html-escaping
https://docs.djangoproject.com/en/1.3/ref/templates/builtins/#escape

¿Qué pasa si sólo se disponde de una versión anterior a la 1.0 y no se usa el filtro escape?

La protección que establece Django de base no se encontrará activa y si, por ejemplo, se necesita un calendario para la aplicación Web en Django, se llegará a la demo online de:

http://www.3captus.com/download/django_calendar
Descargando el código del calendario se observará que en el fichero "urls.py" hay una llamada a la vista addEvent:

(r'^add/.*$', 'addEvent'),

Esta vista, está en el fichero "views.py" en la línea 51, cuyo código es:

cal.addEvent(day, p['name'], when, p['desc'])

Donde:

p = getParams(request, default)

Las variables "name" y "desc" incluyen el contenido enviado directamente por el usuario sin filtrar. En la línea 99 está declarada una función llamada "getParams" que realiza distintas operaciones sobre los parámetros de entrada que puede introducir un usuario, pero ninguna destinada a filtrar la entrada de datos.

Si se inserta en la descripción del formulario el texto que se ha visto antes que es un ataque típico de XSS, >"<script>alert('xss')</script><"

Se producirá el caso que se ha visto anteriormente en el ejemplo y se producirá un ataque de Cross-Site Scripting.

¿Qué pasa si uno se preocupa y se pone en contacto con los desarrolladores del calendario para avisarles del problema?

Captura del mail que se les ha enviado..:

===

mailto: 3captus@xxxx.xxx

On the first test we did on your online demo, http://www.3captus.com/djangoapp/cal/

we have found a Cross-Site Scripting in at least the "Name" and "Description" parameters.

Doing more research, we download the version and run into our local Django copy, we found that, Django avoids Cross-Site Scripting Vulnerabilities using a template filter called "autoescape" on Django V1.0 this runs by default.

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#autoescape

In previous version maybe you can use:

https://docs.djangoproject.com/en/1.0/ref/templates/builtins/#escape

Not sure what Django version are you running on the server but.. If you update the Django copy you'll fix the exploitation of the vulnerability.

If you want to real fix the risk, you'll have to filter based on a blacklist/whitelist the char-set allowed to be used on the "name" and "description" variables. U can do it on the helper function getParameters.

You have 3 different options to solve the vulnerability

1) Update the Django Version (Will use autoescape by default when rendering html)
2) Apply the template filter tag escape when using user input to render html
3) Filter user-input based on black/white-list the allowed charset on the user input.

We are going to release some kind of Proof-Of-Concept on our security site and how Django handles insecure input related with xss, in a week.

Mind you please fix it before?

You can find more information at:

https://docs.djangoproject.com/en/dev/topics/security/#cross-site-scripting-xss-protection

For the PoC of the XSS.

Just insert "><script>alert('xss')</script><!" on the description when adding an Event. or

"><script>alert('xss1')</script><!" in the name of the event.

We want nothing more than keep you safe, can u please fix it?

Thank you very much.

hacktimes.com

===

pues ... consultalo en su web ... ;-D


octubre 13 9:20 a.m.
freed0m dijo:

Gracias Manuel, cuenta con ello y suerte.

octubre 12 11:34 a.m.
Manuel dijo:

Acabo de votar vuestro blog en los Premios Bitácoras 2011. Yo también he presentado el mío al Mejor Blog Tecnológico, es iPadSfera (www.ipadsfera.com). ¿Me ayudáis con vuestro voto? http://bit.ly/oRHyJK Muchísimas gracias y mucha suerte =)

octubre 10 1:25 p.m.
freed0m dijo:

Además, se podrá consultar el código donde Django realiza la conversión. La lista de caracteres tratados esta en el fichero defaultfilters.py en la versión estable y en el fichero html.py en la versión de svn. El conjunto de caracteres que se filtran están en la variable _base_js_escapes hay otros caracteres extra en la variable _js_escapes


Añadir comentario











Búsqueda

Síguenos


El staff de Hacktimes ruega a cualquier persona interesada en la distribución y/o publicación de estos artículos que lo haga sin alterar su contenido y cite a su autor y/o la fuente original. Muchas gracias.

Todos los artículos publicados se encuentran bajo la licencia Creative Commons