Notas de lanzamiento de Django 1.4.11

21 de abril de 2014

Django 1.4.11 corrige tres problemas de seguridad en 1.4.10. Además, la versión vendida de seis en Django, django.utils.six, se ha actualizado a la última versión disponible (1.6.1).

Ejecución inesperada de código utilizando reverse()

Django maneja las URL basándose en una mapeación de patrones regex (representando las URLs) a vistas llamables, y el propio procesamiento de Django consiste en la coincidencia de una URL solicitada contra esos patrones para determinar la vista apropiada a invocar.

Django también proporciona una función conveniente – reverse() – que realiza este proceso en dirección opuesta. La función reverse() toma información sobre una vista y devuelve una URL que invocaría esa vista. Se alienta el uso de reverse() para los desarrolladores de aplicaciones, ya que la salida de reverse() siempre se basa en los patrones de URL actuales, lo que significa que los desarrolladores no necesitan cambiar otro código cuando hacen cambios en las URLs.

Una firma de argumento para reverse() es pasar un camino de Python puntoado al deseeido. En esta situación, Django importará el módulo indicado por ese camino puntoado como parte de la generación del URL resultante. Si tal módulo tiene efectos de lado en tiempo de importación, esos efectos ocurrirán.

Por lo tanto es posible que un atacante cause ejecución de código inesperada, dadas las siguientes condiciones:

  1. Están presentes una o más vistas que construyen una URL basada en la entrada del usuario (comúnmente, un parámetro «next» en una cadena de consulta indicando a dónde redirigir después de completar con éxito una acción).

  2. Están presentes uno o más módulos conocidos por el atacante que existen en la ruta de importación Python del servidor, los cuales realizan ejecución de código con efectos de lado al importar.

Para remediar esto, reverse() ahora solo aceptará y importará caminos puntoados basados en las vistas contenidas en los módulos listados en la configuración de patrones URL del proyecto, para asegurar que solo se importan módulos con los cuales el desarrollador pretendía importarlos.

La caché de páginas anónimas podría revelar token CSRF

Django incluye tanto un framework de caché como un sistema para prevenir ataques de forja de solicitudes cruzadas (CSRF). El sistema de protección contra CSRF se basa en un nonce aleatorio enviado al cliente en una cookie que debe ser enviada por el cliente en futuras solicitudes y, en formularios, un valor oculto que debe ser devuelto con el formulario.

El framework de caché incluye la opción de cachear respuestas a clientes anónimos (es decir, no autenticados).

Cuando la primera solicitud anónima a una página determinada proviene de un cliente que no tiene una cookie CSRF, el marco de caché también cacheará la cookie CSRF y servirá el mismo nonce a otros clientes anónimos que no tienen una cookie CSRF. Esto puede permitir a un atacante obtener un valor válido de la cookie CSRF y realizar ataques que bypassen la comprobación de la cookie.

Para remediar esto, el marco de caché ya no cacheará tales respuestas. La heurística para esto será:

  1. Si la solicitud entrante no envió ninguna cookie, y

  2. Si la respuesta envió una o más cookies, y

  3. Si el encabezado Vary: Cookie está configurado en la respuesta, entonces la respuesta no se cacheará.

Tipos de MySQL

La base de datos MySQL es conocida por «tipcastear» en ciertas consultas; por ejemplo, cuando se consulta una tabla que contiene valores de cadena, pero utilizando una consulta que filtra basada en un valor entero, MySQL silenciosamente convertirá las cadenas a enteros y devolverá un resultado basado en eso.

Si se realiza una consulta sin convertir primero los valores al tipo adecuado, esto puede producir resultados inesperados, similares a lo que ocurriría si la propia consulta hubiera sido manipulada.

Las clases de campos de modelo de Django están conscientes de sus propios tipos y la mayoría de tales clases realizan una conversión explícita de los argumentos de consulta al tipo correcto del nivel de base de datos antes de realizar la consulta. Sin embargo, tres clases de campos de modelo no convirtieron correctamente sus argumentos:

Estos tres campos han sido actualizados para convertir sus argumentos a los tipos correctos antes de realizar consultas.

Además, se advierte a los desarrolladores de campos de modelo personalizados mediante documentación para asegurarse de que sus clases de campo personalizadas realicen las conversiones de tipo adecuadas, y a los usuarios de los métodos de consulta raw() y extra(), que permiten al desarrollador suministrar SQL bruto o fragmentos de SQL, se les aconsejará asegurarse de realizar las conversiones de tipo manuales adecuadas antes de ejecutar consultas.