Django 1.5.6 版本发行说明

2014 年 4 月 21 日

Django 1.5.6 修复了 1.5.5 中的多个错误,包括三个安全问题。

使用 reverse() 时出现意外的代码执行

Django 的 URL 处理基于正则表达式模式(表示 URL)到可调用视图的映射,而 Django 自身的处理包括将请求的 URL 与这些模式进行匹配,以确定要调用的适当视图。

Django 还提供了一个方便的函数 — reverse() — 用于执行与之相反的过程。reverse() 函数接收有关视图的信息,并返回调用该视图的 URL。鼓励应用程序开发人员使用 reverse(),因为``reverse()`` 的输出总是基于当前的 URL 模式,这意味着开发人员在更改 URL 时不需要修改其他代码。

reverse() 的一个参数签名是传递所需视图的点分 Python 路径。在这种情况下,Django 将导入由该点分路径指示的模块,作为生成结果 URL 的一部分。如果这样的模块在导入时具有副作用,那么这些副作用将会发生。

因此,在满足以下条件时,攻击者可能导致意外的代码执行:

  1. 存在一个或多个视图,它们根据用户输入构建 URL(通常是查询字符串中的“next”参数,指示在操作成功完成后重定向到哪里)。
  2. 攻击者知道服务器的 Python 导入路径上存在一个或多个模块,在导入时执行具有副作用的代码。

为了解决这个问题,reverse() 现在将只接受并导入基于项目的 URL 模式配置 中列出的包含视图的模块的点分路径,以确保只有开发人员打算以这种方式导入的模块才能被导入。

缓存匿名页面可能会泄露 CSRF 令牌

Django 包括了一个 缓存框架 和一个用于 防止跨站点请求伪造 (CSRF) 攻击 的系统。CSRF 保护系统基于一个随机的 nonce,它会在 cookie 中发送给客户端,在将来的请求中客户端必须发送该 nonce,同时在表单中还有一个隐藏值,必须与表单一起提交。

缓存框架包括一个选项,用于缓存对匿名(即未经认证的)客户端的响应。

当第一个对指定页面的匿名请求来自没有 CSRF cookie 的客户端时,缓存框架还会缓存 CSRF cookie,并为没有 CSRF cookie 的其他匿名客户端提供相同的随机数。这可能使攻击者获得有效的 CSRF cookie 值,并执行绕过 cookie 检查的攻击。

为了解决这个问题,缓存框架将不再缓存此类响应。启发式方法将是:

  1. 如果传入的请求没有提交任何 cookie,且
  2. 如果响应发送了一个或多个 cookie,且
  3. 如果在响应中设置了 Vary: Cookie 头,那么该响应将不会被缓存。

MySQL 类型转换

众所周知,MySQL 数据库会对某些查询进行“类型转换”;例如,在查询包含字符串值的表时,但使用基于整数值进行过滤的查询,MySQL 首先会默默地将字符串强制转换为整数,然后返回基于该整数的结果。

如果在未先将值转换为适当类型的情况下执行查询,这可能产生意外的结果,类似于查询本身被操作时会发生的情况。

Django 的模型字段类知道它们自己的类型,大多数此类字段在查询之前会将查询参数明确转换为正确的数据库级别类型。然而,有三个模型字段类没有正确地转换它们的参数:

在查询之前,这三个字段已经更新为将参数转换为正确的类型。

此外,自定义模型字段的开发人员现在通过文档受到警告,需要确保他们的自定义字段类能够执行适当的类型转换,以及使用 raw()extra() 查询方法的用户将被建议确保在执行查询之前进行适当的手动类型转换,因为这些方法允许开发人员提供原始 SQL 或 SQL 片段。

漏洞修复

此外,Django 内置的 six 版本 django.utils.six 已升级到最新版本 (1.6.1)。