Django 1.6.3 release notes

2014年4月21日

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

Unexpected code execution using reverse()

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

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

reverse()的一个参数签名是通过一个虚线的Python路径到所需的视图。在这种情况下,Django将导入由该虚线路径指示的模块,作为生成结果URL的一部分。如果这样的模块有进口时间副作用,那些副作用将发生。

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

  1. 存在基于用户输入构建URL的一个或多个视图(通常,查询字符串中的“下一个”参数,其指示在成功完成动作之后重定向的位置)。
  2. 攻击者知道一个或多个模块存在于服务器的Python导入路径上,这些模块在导入时执行代码执行并带有副作用。

为了解决这个问题,reverse()现在将只接受和导入基于项目URL pattern configuration中列出的包含视图的模块的点状路径,以确保只有模块旨在以这种方式导入的开发者可以或将被导入。

Caching of anonymous pages could reveal CSRF token

Django包括caching frameworkpreventing cross-site request forgery (CSRF) attacksCSRF保护系统基于在cookie中发送到客户端的随机随机数,该cookie必须由客户端在未来请求时发送,并且以表单形式存储必须与表单一起提交的隐藏值。

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

当对给定页面的第一匿名请求是由没有CSRF cookie的客户端时,高速缓存框架还将缓存CSRF cookie并且向没有CSRF cookie的其他匿名客户端提供相同的随机数。这可以允许攻击者获得有效的CSRF cookie值,并执行绕过对cookie的检查的攻击。

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

  1. 如果传入请求未提交任何Cookie,和
  2. 如果响应确实发送了一个或多个Cookie,和
  3. 如果响应中设置了Vary: Cookie头,那么响应将不会被缓存。

MySQL typecasting

MySQL数据库被称为对某些查询“typecast”;例如,当查询包含字符串值的表,但使用基于整数值过滤的查询时,MySQL将首先将字符串强制转换为整数,并返回基于该值的结果。

如果执行查询时没有首先将值转换为适当的类型,这可能会产生意外的结果,类似于如果查询本身被操纵会发生的结果。

Django的模型字段类知道它们自己的类型,并且大多数这样的类在查询之前执行查询参数到正确的数据库级类型的显式转换。但是,三个模型字段类没有正确转换其参数:

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

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

select_for_update() requires a transaction

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

进行此更改是因为此类错误可能是由于包含预期全局事务的应用程序(例如,ATOMIC_REQUESTS设置为True)或Django的旧自动提交行为,在没有它们的项目中运行;并且此外,这样的错误可以表现为数据腐败错误。

如果在作为TransactionTestCase而不是TestCase的子类的测试类中使用select_for_update(),则此更改可能会导致测试失败。

Other bugfixes and changes

  • 从GeoIP库检索的内容现在可以从其默认的iso-8859-1编码(#21996)正确解码。
  • 在使用bulk_create()ForeignObject#21566)时固定AttributeError
  • Fixed crash of QuerySets that use F() + timedelta() when their query was compiled more once (#21643).
  • 防止IntegerField子类的类属性被其__init__方法(#22245)中的代码覆盖,防止自定义widget
  • 改进了strip_tags()的准确性(但仍然无法保证HTML安全的结果,如文档中所述)。
  • 修正了django.contrib.gis SQL编译器中非混凝土字段(#22250)的回归。
  • 在运行具有网址前缀(#21795)的网站时,固定ModelAdmin.preserve_filters
  • 修复了未设置PATH环境变量(#22256)时find_command管理实用程序中的崩溃问题。
  • 在Windows上固定changepassword#22364)。
  • 避免MySQL上的阴影死锁异常(#22291)。
  • _set_autocommit#22321)中包含数据库异常。
  • 在关闭数据库连接或数据库服务器断开连接时(#21239#21202)修复了原子性
  • prefetch_related中的固定回归,导致相关对象查询包含不必要的连接(#21760)。

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