安全概述
这份文档是 Django 的安全功能的概述。 它包括给 Django 驱动的网站一些加固建议。
跨站脚本 (XSS) 防护
XSS 攻击允许用户注入客户端脚本到其他用户的浏览器里。 这通常是通过存储在数据库中的恶意脚本,它将检索并显示给其他用户,或者通过让用户点击一个链接,这将导致攻击者的 JavaScript 被用户的浏览器执行。 然而,XSS 攻击可以来自任何不受信任的源数据,如 Cookie 或 Web 服务,任何没有经过充分处理就包含在网页中的数据。
使用 Django 模板保护你免受多数 XSS 攻击。 然而,重要的是要了解它提供了什么保护及其局限性。
Django 模板会 编码特殊字符 ,这些字符在 HTML 中都是特别危险的。 虽然这可以防止大多数恶意输入的用户,但它不能完全保证万无一失。 例如,它不会防护以下内容:
<style class=>...</style>
如果 var
设置为 'class1 onmouseover=javascript:func()'
, 这可能会导致在未经授权的 JavaScript 的执行,取决于浏览器如何呈现不完整的 HTML。 (对属性值使用引号可以修复这种情况。)
同样重要的是 is_safe
要特别小心的用在 自定义模板标签, safe
模板标签, mark_safe
,还有 autoescape 被关闭的时候。
此外,如果您使用的是模板系统输出 HTML 以外的东西,可能会有完全不同的字符和单词需要编码。
你也应该在数据库中存储 HTML 的时候要非常小心,尤其是当 HTML 被检索然后展示出来。
跨站请求伪造 (CSRF) 防护
CSRF 攻击允许恶意用户在另一个用户不知情或者未同意的情况下,以他的身份执行操作。
Django 对大多数类型的 CSRF 攻击有内置的保护,在适当情况下你可以 开启并使用它 。 然而,对于任何解决技术,都有它的局限性。 例如,CSRF 模块可以在全局范围内或为特定视图被禁用 。 您应该只在您知道在做什么的情况下操作。 还有其他 限制 如果你的网站有子域名并且在你的控制之外。
CSRF 防护 是通过检查每个 POST 请求的一个随机数(nonce)来工作。 这确保了恶意用户不能简单“回放”你网站上面表单的 POST,以及让另一个登录的用户无意中提交表单。恶意用户必须知道这个随机数,它是用户特定的(存在 cookie 里)。
使用 HTTPS 来部署的时候, CsrfViewMiddleware
会检查 HTTP referer 协议头是否设置为同源的 URL(包括子域和端口)。因为 HTTPS 提供了附加的安全保护,转发不安全的连接请求时,必须确保链接使用 HTTPS,并使用 HSTS 支持的浏览器。
使用 csrf_exempt
装饰器来标记视图时,要非常小心,除非这是极其必要的。
SQL 注入保护
SQl 注入是一种攻击类型,恶意用户可以在系统数据库中执行任意 SQL 代码。这可能会导致记录删除或者数据泄露。
通过使用 Django 的查询集,产生的 SQL 会由底层数据库驱动正确地转义。然而,Django 也允许开发者编写 原始查询 或者执行 自定义 sql 。这些功能应该谨慎使用,并且你应该时刻小心正确转义任何用户可以控制的参数。另外,你在使用 extra()
的时候应该谨慎行事。
点击劫持保护
点击劫持是一类攻击,恶意站点在一个 frame 中包裹了另一个站点。这类攻击可能导致用户被诱导在目标站点做出一些无意识的行为。
Django 在 X-Frame-Options 中间件
的表单中中含有 点击劫持保护 ,它在支持的浏览器中可以保护站点免于在 frame 中渲染。也可以在每个视图中禁止这一保护,或者配置要发送的额外的协议头。
对于任何不需要将页面包装在三方站点的 frame 中,或者只需要包含它的一部分的站点,都强烈推荐启用这一中间件。
SSL / HTTPS
把你的站点部署在 HTTPS 下总是更安全的,尽管不是在所有情况下都有效。如果不这样,恶意的网络用户可能会嗅探授权证书,或者其他在客户端和服务端之间传输的信息,或者一些情况下 -- 活跃的网络攻击者 -- 会修改在两边传输的数据。
如果你想要 HTTPS 提供保护,那么需要在你的服务器上启用它,可能还需要去做一些额外的操作
- 如果必要的话,设置
SECURE_PROXY_SSL_HEADER
,确保你已经彻底了解警告。未能实现它会导致 CSRF 方面的缺陷,也是很危险的! - 设置重定向,那样通过 HTTP 的请求会重定向到 HTTPS。
这可以通过自定义的中间件来实现。请注意
SECURE_PROXY_SSL_HEADER
下的警告。对于反向代理的情况,配置 web 主服务器来重定向到 HTTPS 或许是最简单也许是最安全的做法。 - 使用“安全的”cookie。
如果浏览器的连接一开始通过 HTTP,这是大多数浏览器的通常情况,已存在的 cookie 可能会被泄露。因此,你应该将
SESSION_COOKIE_SECURE
和CSRF_COOKIE_SECURE
设置为True
。这会使浏览器只在 HTTPS 连接中发送这些 cookie。要注意这意味着会话在 HTTP 下不能工作,并且 CSRF 保护功能会在 HTTP 下阻止接受任何 POST 数据(如果你把所有 HTTP 请求都重定向到 HTTPS 之后就没问题了)。 - 使用 HTTP 强制安全传输 (HSTS)
HSTS 是一个 HTTP 协议头,它通知浏览器,到特定站点的所有链接都一直使用 HTTPS。通过和重定向 HTTP 请求到 HTTPS 一起使用,确保连接总是享有附加的 SSL 安全保障,由一个已存在的成功的连接提供。HSTS 通常在 web 服务器上面配置。
Host 协议头验证
在某些情况下,Django 使用客户端提供的 Host
协议头来构造 URL。虽然这些值可以被审查,来防止跨站脚本攻击(XSS),但是一个假的 Host
值可以用于跨站请求伪造(CSRF),有害的缓存攻击,以及 email 中的有害链接。
因为即使表面上看起来安全的 web 服务器也容易被篡改 主机头
,Django 再次在 django.http.HttpRequest.get_host() 这个方法中验证主机头这个 ALLOWED_HOSTS 的设置 Django validates Host
headers against the ALLOWED_HOSTS
setting in the django.http.HttpRequest.get_host()
method.
验证只通过 get_host()
来应用;如果你的代码从 request.META
中直接访问 Host
协议头,就会绕开这一安全防护。
详见完整的 ALLOWED_HOSTS
文档。
警告
本文档的先前版本建议配置 Web 服务器以确保其验证传入的 HTTP Host
头。虽然这仍然是建议,在许多常见的 Web 服务器,似乎验证 Host
头的配置可能实际上不这样做。例如,即使 Apache 配置为使您的 Django 站点从设置了 ServerName
的非默认虚拟主机提供,HTTP 请求仍然可以匹配此虚拟主机并提供假 Host
标头。因此,Django 现在要求您明确设置 ALLOWED_HOSTS
,而不是依赖于 Web 服务器配置。
另外,就像 1.3.1,如果你的配置需要它的话,Django 需要你显式开启对 X-Forwarded-Host
协议头的支持(通过 USE_X_FORWARDED_HOST
设置)。
Session 会话安全
类似于部署在站点上的 CSRF 限制 使不受信任的用户不能访问任何子域, django.contrib.sessions
也有一些限制。详见 安全中会话的话题指南 。
用户上传的内容
注意
考虑 在云服务器或 CDN 上面部署静态文件 来避免一些此类问题。
- 如果你的站点接受上传文件,强烈推荐你在 web 服务器配置中,将这些上传限制为合理的大小,来避免拒绝服务(DOS)攻击。在 Apache 中,这可以简单地使用 LimitRequestBody 指令。
- 如果你自己处理静态文件,确保像 Apache 的
mod_php
的处理器已关闭,它会将静态文件执行为代码。你并不希望用户能够通过上传和请求一个精心构造的文件来执行任意代码。 - 当媒体以不遵循安全最佳做法的方式提供时,Django 的媒体上传处理带来一些漏洞。具体来说,如果 HTML 文件包含有效的 PNG 标头,然后是恶意 HTML,则可以将其上传为图片。此文件将通过对 Django 用于
ImageField
图像处理(Pillow)的库的验证。当此文件随后显示给用户时,可能会显示为 HTML,具体取决于 Web 服务器的类型和配置。在框架级别上没有安全验证所有用户上传的文件内容的防弹技术解决方案,但是,还可以采取一些其他步骤来减轻这些攻击:
- 通过始终提供来自不同顶级或二级域的用户上传的内容,可以防止一类攻击。这可以防止受到 同源策略 保护(例如跨站点脚本)阻止的任何漏洞利用。For example, if your site runs on
example.com
, you would want to serve uploaded content (theMEDIA_URL
setting) from something likeusercontent-example.com
. 不足以提供来自usercontent.example.com
等子网域的内容。 - 除此之外,应用可以选择为用户上传的文件定义一个允许的文件扩展名的白名单,并且配置 web 服务器直处理这些文件。
- 通过始终提供来自不同顶级或二级域的用户上传的内容,可以防止一类攻击。这可以防止受到 同源策略 保护(例如跨站点脚本)阻止的任何漏洞利用。For example, if your site runs on
额外的安全话题
虽然 Django 提供了开箱即用的,良好的安全保护,但是合理地部署你的应用,以及利用 web 服务器、操作系统和其他组件的安全保护仍然很重要。
- 确保你的 Python 代码在 web 服务器的根目录外。这会确保你的 Python 代码不会意外被解析为纯文本(或者意外被执行)。
- 小心处理任何 用户上传的文件 。
- Django 并不限制验证用户的请求。要保护对验证系统的暴力破解攻击,你可以考虑部署一个 DJango 的插件或者 web 服务器模块来限制这些请求。
- 秘密保存
SECRET_KEY
。 - 使用防火墙来限制缓存系统和数据库的访问是个好主意。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论