发布的安全版本
今天,Django 团队发布了多个版本——Django 1.2.5 和 Django 1.1.4——来解决三个报告给我们的安全问题。我们强烈建议所有使用受影响版本的 Django 用户立即升级。
CSRF 处理中的漏洞
Django 包含一个 CSRF 防护机制,该机制利用插入到传出表单中的令牌。然后,中间件在表单提交时检查令牌是否存在,并对其进行验证。
但是,以前我们的 CSRF 防护对 AJAX 请求做了一个例外,其依据如下:
- 许多 AJAX 工具包在使用
XMLHttpRequest
时会添加X-Requested-With
标头。 - 浏览器对
XMLHttpRequest
具有严格的同源策略。 - 在浏览器的上下文中,这种自定义标头唯一可以添加的方式是使用
XMLHttpRequest
。
因此,为了方便使用,我们根据 X-Requested-With
标头,不对看起来像是 AJAX 的请求应用 CSRF 检查。Ruby on Rails Web 框架也有类似的豁免。
最近,Google 的工程师让 Ruby on Rails 开发团队的成员意识到,浏览器插件和重定向的组合可以允许攻击者在对任何网站的请求中提供自定义 HTTP 标头。这可以让伪造的请求看起来像 AJAX 请求,从而绕过依赖 AJAX 请求同源性的 CSRF 防护。
Rails 团队的 Michael Koziarski 将此问题提请我们注意,我们能够制作出一个概念验证,证明 Django 的 CSRF 处理中存在同样的漏洞。
为了解决这个问题,Django 现在将对所有请求应用完整的 CSRF 验证,而不管其明显的 AJAX 来源如何。从技术上讲,这与向后兼容性不符,但在这种情况下,安全风险被认为超过了兼容性问题。
此外,Django 现在除了在表单提交本身中接受 CSRF 令牌外,还将在自定义 HTTP 标头 X-CSRFTOKEN
中接受 CSRF 令牌,以便与允许将自定义标头插入所有 AJAX 请求的流行 JavaScript 工具包轻松使用。
以下使用 jQuery JavaScript 工具包的示例演示了这一点;对 jQuery 的 ajaxSetup
的调用将导致所有 AJAX 请求在自定义 X-CSRFTOKEN
标头中发送回 CSRF 令牌。
$.ajaxSetup({ beforeSend: function(xhr, settings) { if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) { // Only send the token to relative URLs i.e. locally. xhr.setRequestHeader("X-CSRFToken", $("#csrfmiddlewaretoken").val()); } } });
作为参考,可以在这里查看 Ruby on Rails 团队关于此问题的公告 here.
文件字段渲染中的潜在 XSS
Django 的表单系统包括用于执行文件上传的表单字段和小部件;在渲染这些字段时,会显示当前存储在字段中的文件名。正如 Trac 用户“e.generalov”所报告的那样,在渲染过程中,文件名未经转义就显示出来。
在许多情况下,这不会导致跨站点脚本漏洞,因为文件存储后端可以并且鼓励(并且 Django 提供的默认后端确实如此)根据其要求对提供的文件名进行清理。但是,在未进行清理或清理不足的后端中出现漏洞的风险使得 Django 现在将在表单渲染中自动转义文件名。
Windows 上的目录遍历漏洞
Django 基于文件的会话存储后端将会话数据存储在一个以会话键命名的文件中。此后端验证提交在会话 Cookie 中的键是否不包含由 Python 的 os.path.sep
指定的文件系统路径分隔符字符,如果在键中找到该字符,则会引发异常。
但是,正如 Paul McMillan 向 Django 团队报告的那样,这在 Windows 上是不够的,因为 Windows 上的文件系统操作接受多个潜在的路径分隔符(Windows 的 os.path.sep
是反斜杠字符;正斜杠字符也被接受)。由于其他验证机制——会话也与内容的哈希值一起存储,并且在会话反序列化时会验证哈希值——因此这不会自动允许任意加载或执行文件。但是,由于会话重放的可能性,或者如果攻击者设法绕过会话验证,则会出现更严重的漏洞,因此基于文件的会话后端现在将使用一个明确的字符白名单,这些字符可能出现在会话键中。此白名单排除了所有有效的路径分隔符。
受影响的版本
上面描述的所有三个问题都存在于以下当前受支持的 Django 版本中:
- Django 开发主干
- Django 1.2
- Django 1.1
解决方案
已将补丁应用于 Django 主干以及 1.2 和 1.1 发布分支,这些补丁解决了上述问题。补丁可以直接从以下变更集中获取:
- Django 主干:15464(用于 CSRF 问题)、15470(用于文件字段问题)和 15467(用于文件存储问题)。
- Django 1.2:15465(用于 CSRF 问题)、15471(用于文件字段问题)和 15468(用于文件存储问题)。
- Django 1.1:15466(用于 CSRF 问题)、15472(用于文件字段问题)和 15469(用于文件存储问题)。
已发布以下新版本:
由于 Django 主干目前处于测试阶段,强烈建议用户不要在其上运行生产部署;但是,如果您目前正在这样做,我们敦促您立即升级到最新主干,其中包含针对这些问题的补丁。
关于安全的一般说明
与往常一样,我们要求通过私人电子邮件 security@djangoproject.com 报告潜在的安全问题,而不是通过 Django 的 Trac 实例或 django-developers 列表。
如果您是或代表 Django 的第三方分销商,并且未从 Django 发布管理员处收到有关此公告的通知电子邮件,请联系 james@b-list.org
。