Django 1.6.3发行说明

2014年4月21日

Django 1.6.3修复了1.6.2中的几个错误,包括三个安全问题,并进行了一次向后不兼容的更改:

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

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

Django还提供便利功能-- reverse() --它以相反的方向执行这个过程。这个 reverse() 函数获取有关视图的信息并返回将调用该视图的URL。使用 reverse() 对于应用程序开发人员,作为 reverse() 始终基于当前的URL模式,这意味着开发人员在更改URL时不需要更改其他代码。

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

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

  1. 存在一个或多个基于用户输入构造URL的视图(通常是querystring中的“next”参数,指示成功完成操作后重定向到何处)。

  2. 攻击者知道一个或多个模块存在于服务器的python导入路径上,该路径执行代码执行时会对导入产生副作用。

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

缓存匿名页面可能会显示CSRF令牌

Django包括 caching framework 和一个系统 preventing cross-site request forgery (CSRF) attacks . CSRF保护系统基于一个随机的nonce,该nonce以cookie形式发送给客户,客户必须在未来请求时发送该cookie,并且在表单中,隐藏的值必须与表单一起提交。

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

当对给定页面的第一个匿名请求是由没有CSRF cookie的客户端发出时,缓存框架还将缓存CSRF cookie,并向没有CSRF cookie的其他匿名客户端提供相同的nonce。这允许攻击者获取有效的CSRF cookie值,并执行绕过cookie检查的攻击。

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

  1. 如果传入请求未提交任何cookie,以及

  2. 如果响应确实发送了一个或多个cookie,并且

  3. 如果 Vary: Cookie 在响应上设置了头,则不会缓存响应。

MySQL类型转换

MySQL数据库在某些查询中被称为“类型转换”;例如,当查询包含字符串值的表时,但使用基于整数值筛选的查询时,MySQL将首先静默地将字符串强制为整数,并基于该值返回结果。

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

Django的模型字段类知道它们自己的类型,大多数此类类在查询前将查询参数显式转换为正确的数据库级类型。但是,三个模型字段类没有正确转换其参数:

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

此外,自定义模型字段的开发人员现在通过文档得到警告,以确保他们的自定义字段类将执行适当的类型转换,并且 raw()extra() 将建议使用允许开发人员提供原始SQL或SQL片段的查询方法,以确保它们在执行查询之前执行适当的手动类型转换。

select_for_update() 需要一个事务

历史上,使用 select_for_update() 可以在事务外的自动提交模式下执行。在django 1.6之前,django的自动事务模式允许使用它锁定记录,直到下一次写入操作。Django1.6引入了数据库级的自动提交;从那时起,在这样的上下文中执行会使 select_for_update() . 因此,现在假定它是一个错误并引发异常。

之所以进行此更改,是因为这些错误可能是由包含预期全局事务的应用程序(例如 ATOMIC_REQUESTS 设置为 True 或者Django以前的自动提交行为,在没有它们的情况下运行的项目中;而且,这些错误可能表现为数据损坏错误。

如果您使用 select_for_update() 在属于的子类的测试类中 TransactionTestCase 而不是 TestCase .

其他错误修复和更改

  • 从geoip库中检索到的内容现在已从其默认值正确解码。 iso-8859-1 编码 (#21996

  • 固定的 AttributeError 使用时 bulk_create() 具有 ForeignObject (#21566

  • 固定崩溃 QuerySet 使用的 F() + timedelta() 当他们的查询再次编译时 (#21643

  • 阻止自定义 widget 的类属性 IntegerField 子类不会被其中的代码覆盖 __init__ 方法 (#22245

  • 改进 strip_tags() 准确性(但它仍然不能保证HTML安全结果,如文档中所述)。

  • 修正了在 django.contrib.gis 非具体字段的SQL编译器 (#22250

  • 固定的 ModelAdmin.preserve_filters 运行带有URL前缀的网站时 (#21795

  • 修复了 find_command 管理实用程序 PATH 未设置环境变量 (#22256

  • 固定的 changepassword 在Windows上 (#22364

  • 避免在MySQL上隐藏死锁异常 (#22291

  • 包装的数据库异常 _set_autocommit (#22321

  • 修复了关闭数据库连接或数据库服务器断开连接时的原子性 (#21239#21202

  • 固定回归 prefetch_related 导致相关对象查询包含不必要的联接 (#21760

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