发布的安全版本

作者:James Bennett 发布于 2013年2月19日

今天,Django 团队发布了多个版本——Django 1.3.6、Django 1.4.4 和 Django 1.5 发布候选版本 2——作为我们安全流程的一部分。

这些版本修复了向我们报告的多个问题,并涉及一项重要的对最终用户可见的更改,因此请仔细阅读这些说明。

摘要

这些安全版本修复了四个问题:一个潜在的网络钓鱼途径,一个拒绝服务途径,一个信息泄露问题,以及一系列 XML 漏洞

以下是每个问题及其解决方案的简要摘要

  • 问题:主机头欺骗:攻击者可能导致 Django 生成和显示链接到任意域名的 URL。这可以作为网络钓鱼攻击的一部分使用。这些版本通过引入一个新的设置ALLOWED_HOSTS来解决此问题,该设置指定了您的网站已知响应的域名的白名单。

    重要提示:默认情况下,Django 1.3.6 和 1.4.4 将ALLOWED_HOSTS设置为允许所有主机。这意味着要实际修复安全漏洞,您应该在升级后立即自行定义此设置。

  • 问题:表单集拒绝服务:攻击者可以滥用 Django 对表单集中表单数量的跟踪来造成拒绝服务攻击。这已通过添加默认表单最大数量 1,000 来修复。如果您愿意,您仍然可以手动指定更大的max_num,但 1,000 对任何人都应该足够了。

  • 问题:XML 攻击:Django 的序列化框架容易受到通过 XML 实体扩展和外部引用进行攻击;这现在已修复。但是,如果您在应用程序的其他部分解析任意 XML,我们建议您查看defusedxml Python 包,这些包可以修复您在任何解析 XML 的地方,而不仅仅是通过 Django 的序列化框架。

  • 问题:通过管理员历史记录日志泄露数据:Django 的管理界面可能会通过其历史记录日志公开假定的隐藏信息。这已修复。

有关更多详细信息,请继续阅读。

问题:主机头欺骗

之前的一些 Django 安全版本试图解决与 HTTPHost标头相关的持久性问题。Django 包含代码——并且一些与 Django 自身一起发布的功能利用了该代码——用于基于传入 HTTP 请求构建完整限定的 URL。根据配置,这会使用Host标头,因此能够导致 Django 应用程序响应任意Host标头的攻击者可以导致 Django 生成并向最终用户显示任意域上的 URL。

此问题的先前迭代(请参阅 CVE-2011-4139 和 CVE-2012-4520)侧重于加强 Django 对Host标头的解析,以消除攻击者——使用诸如其提交的Host标头中的用户名/密码对等技术——可以利用此的各种方法。

但是,最终,Django 本身无法确保攻击者无法提交并导致 Django 接受任意Host标头。在已部署的 Django 实例中正确保护此操作还需要配置 Web 服务器,并且配置和可实现的安全级别会因所使用的服务器而异。

鉴于此,django.http.HttpRequestget_host()方法现在将针对新的设置ALLOWED_HOSTS验证Host标头。此设置是一个字符串列表(默认情况下为空列表),对应于标头的可接受值,并提供了一些对通配符的支持。

不使用get_host()的代码或无需借助 HTTP 标头即可确定当前主机名的 Django 配置(即,启用 Django 的站点框架时)不会受到此更改的影响。

由于这是对先前问题的强化/收紧,因此它没有新的 CVE 编号。

问题:XML 攻击

Django 的序列化框架包括对序列化到 XML 和从 XML 反序列化的支持。Django 的 XML 反序列化容易受到实体扩展和外部实体/DTD 攻击。

为了解决此问题,Django 的 XML 反序列化程序不再允许 DTD、执行实体扩展或获取外部实体/DTD。请注意,这仅保护 Django 的 XML 序列化框架;如果您的应用程序解析 XML,我们建议您查看defusedxml Python 包,这些包可以修复 Python 本身的问题。

由于此问题也影响 Python 的 XML 库,因此它由 Python 的 CVE-2013-1664 和 CVE-2013-1665 涵盖。

问题:通过管理员历史记录日志泄露数据

Django 的捆绑管理界面会保留所采取操作的日志,保留通过管理界面公开的任何对象的记录。此历史记录视图除了确认用户是否有权访问管理界面外,不会执行任何权限检查;因此,任何具有管理员访问权限的用户都可以查看任何在管理界面中可访问的对象的历史记录,并查看对对象所做的每个更改的摘要。

为了解决此问题,对象的管理员历史记录视图现在将执行与同一对象的其他管理员视图相同的权限检查。

此问题是 CVE-2013-0305。

问题:表单集拒绝服务

Django 的表单库包括用于生成表单集的工具——单个表单的多个实例,可同时提交(例如,用于对类似对象进行批量编辑/更新)。表单集允许一个参数max_num,指定可以显示的单个表单的最大数量。然后,表单集中的隐藏输入指定要提交的表单数量。

Django 接受提交的隐藏值,并尝试实例化这么多表单对象。足够大的值会导致极端的内存消耗;在这种情况下,超过sys.maxint的值将导致 HTTP 500 响应(由于来自过大值的未捕获OverflowError)。在前一种情况下,结果是有效的拒绝服务攻击。在后一种情况下,攻击者可以导致任意的服务器错误。

为了解决此问题,Django 现在将为表单的最大数量提供(足够大)的默认值,当未提供max_num时将使用该值。应用程序开发人员仍然可以手动指定max_num以满足其应用程序的需求,但在没有此值的情况下,默认值——1000——将确保攻击者无法导致溢出错误或过度的内存消耗。

此问题是 CVE-2013-0306。

受影响的版本

上述问题会影响以下版本的 Django

  • Django 主开发分支
  • Django 1.5 发布分支(即将成为 Django 1.5)
  • Django 1.4 发布分支
  • Django 1.3 发布分支

解决方案

已将补丁应用于 Django 的主开发分支以及 1.5、1.4 和 1.3 发布分支,以解决上述问题。补丁可以直接从以下更改集中获取。

在开发主分支上

在 Django 1.5 发布分支上

在 Django 1.4 发布分支上

在 Django 1.3 发布分支上

已发布以下新版本

致谢

Host标头问题的后续工作再次来自 James Kettle。Rails 的 Michael Koziarski 向我们报告了 XML 漏洞。补丁的基本内容来自 Christian Heimes。Orange Tsai 报告了管理员信息泄露问题。Mozilla 报告了表单集验证问题。

有关安全报告的常规说明

与往常一样,我们要求通过私人电子邮件向security@djangoproject.com报告潜在的安全问题,而不是通过 Django 的 Trac 实例或 django-developers 列表。请参阅我们的安全策略以获取更多信息。

返回顶部