Django 中的安全性 — Django 文档

来自菜鸟教程
Django/docs/3.1.x/topics/security
跳转至:导航、​搜索

Django 中的安全性

本文档概述了 Django 的安全功能。 它包括有关保护 Django 支持的站点的建议。

跨站脚本 (XSS) 保护

XSS 攻击允许用户将客户端脚本注入其他用户的浏览器。 这通常是通过将恶意脚本存储在数据库中来实现的,在那里它会被检索并显示给其他用户,或者让用户点击一个链接,这将导致攻击者的 JavaScript 被用户的浏览器执行。 然而,XSS 攻击可能源自任何不受信任的数据源,例如 cookie 或 Web 服务,只要数据在包含在页面中之前没有得到充分的净化。

使用 Django 模板可以保护您免受大多数 XSS 攻击。 但是,了解它提供的保护及其局限性很重要。

Django 模板 转义对 HTML 尤其危险的特定字符 。 虽然这可以保护用户免受大多数恶意输入的侵害,但并非完全万无一失。 例如,它不会保护以下内容:

<style class={{ var }}>...</style>

如果 var 设置为 'class1 onmouseover=javascript:func()',这可能会导致未经授权的 JavaScript 执行,具体取决于浏览器呈现不完美 HTML 的方式。 (引用属性值可以解决这种情况。)

在将 is_safe 与自定义模板标签、:tfilter:`safe` 模板标签、mark_safe 以及自动转义打开时要特别小心也很重要离开。

此外,如果您使用模板系统输出 HTML 以外的内容,则可能会有完全独立的字符和单词需要转义。

在数据库中存储 HTML 时也应该非常小心,尤其是在检索和显示该 HTML 时。


跨站请求伪造 (CSRF) 保护

CSRF 攻击允许恶意用户在其他用户不知情或不同意的情况下使用该用户的凭据执行操作。

Django 具有针对大多数类型 CSRF 攻击的内置保护,前提是您已启用 并在适当的情况下使用它 。 但是,与任何缓解技术一样,也存在局限性。 例如,可以全局或针对特定视图禁用 CSRF 模块。 只有当您知道自己在做什么时,才应该这样做。 如果您的站点具有不受您控制的子域,则还有其他 限制

CSRF 保护工作 通过检查每个 POST 请求中的秘密。 这可确保恶意用户无法“重放”表单 POST 到您的网站,并让其他登录用户在不知不觉中提交该表单。 恶意用户必须知道用户特定的秘密(使用 cookie)。

当使用 HTTPS 部署时,CsrfViewMiddleware 将检查 HTTP 引用标头是否设置为相同来源的 URL(包括子域和端口)。 由于 HTTPS 提供了额外的安全性,因此必须通过转发不安全的连接请求并为受支持的浏览器使用 HSTS 来确保连接使用 HTTPS 可用。

除非绝对必要,否则在使用 csrf_exempt 装饰器标记视图时要非常小心。


SQL注入保护

SQL 注入是一种攻击,恶意用户能够在数据库上执行任意 SQL 代码。 这可能导致记录被删除或数据泄露。

Django 的查询集不受 SQL 注入的影响,因为它们的查询是使用查询参数化构造的。 查询的 SQL 代码与查询的参数分开定义。 由于参数可能是用户提供的,因此不安全,因此它们会被底层数据库驱动程序转义。

Django 还赋予开发人员编写 原始查询 或执行 自定义 sql 的权力。 这些功能应该谨慎使用,并且您应该始终小心正确地转义用户可以控制的任何参数。 此外,在使用 extra()RawSQL 时应该小心。


点击劫持保护

点击劫持是一种攻击,其中恶意站点将另一个站点包装在框架中。 这种攻击可能会导致毫无戒心的用户被诱骗在目标站点上执行意外操作。

Django 以 X-Frame-Options 中间件 的形式包含 点击劫持保护 ,它在支持的浏览器中可以防止站点在框架内呈现。 可以在每个视图的基础上禁用保护或配置发送的确切标头值。

强烈建议将中间件用于不需要第三方站点将其页面包装在框架中的任何站点,或者只需要允许站点的一小部分。


SSL/HTTPS

将站点部署在 HTTPS 之后总是更好的安全性。 如果没有这个,恶意网络用户就有可能嗅探身份验证凭据或客户端和服务器之间传输的任何其他信息,并且在某些情况下(active 网络攻击者)可以更改向任一方向发送的数据。

如果您想要 HTTPS 提供的保护,并在您的服务器上启用它,您可能需要一些额外的步骤:

  • 如有必要,设置 :setting:`SECURE_PROXY_SSL_HEADER`,确保您已彻底理解那里的警告。 不这样做可能会导致 CSRF 漏洞,并且不正确执行也可能是危险的!

  • :setting:`SECURE_SSL_REDIRECT` 设置为 True,以便将 HTTP 上的请求重定向到 HTTPS。

    请注意 :setting:`SECURE_PROXY_SSL_HEADER` 下的警告。 对于反向代理,将主 Web 服务器配置为重定向到 HTTPS 可能更容易或更安全。

  • 使用“安全”cookie。

    如果浏览器最初通过 HTTP(大多数浏览器的默认设置)进行连接,则现有 cookie 可能会泄露。 因此,您应该将 :setting:`SESSION_COOKIE_SECURE`:setting:`CSRF_COOKIE_SECURE` 设置设置为 True。 这会指示浏览器仅通过 HTTPS 连接发送这些 cookie。 请注意,这意味着会话将无法通过 HTTP 工作,并且 CSRF 保护将阻止通过 HTTP 接受任何 POST 数据(如果您将所有 HTTP 流量重定向到 HTTPS,这会很好)。

  • 使用 HTTP 严格传输安全 (HSTS)

    HSTS 是一个 HTTP 标头,它通知浏览器以后与特定站点的所有连接都应始终使用 HTTPS。 与通过 HTTP 将请求重定向到 HTTPS 相结合,这将确保连接始终享有 SSL 的附加安全性,前提是发生了一个成功的连接。 HSTS 可以配置为 :setting:`SECURE_HSTS_SECONDS`:setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS`:setting:`SECURE_HSTS_PRELOAD`,服务器。


主机头验证

在某些情况下,Django 使用客户端提供的 Host 标头来构造 URL。 虽然对这些值进行了清理以防止跨站点脚本攻击,但伪造的 Host 值可用于跨站点请求伪造、缓存中毒攻击和电子邮件中的链接中毒。

因为即使看似安全的 Web 服务器配置也容易受到伪造 Host 标头的影响,所以 Django 会根据 django 中的 :setting:`ALLOWED_HOSTS` 设置验证 Host 标头.http.HttpRequest.get_host() 方法。

此验证仅适用于 get_host(); 如果您的代码直接从 request.META 访问 Host 标头,则您将绕过此安全保护。

有关更多详细信息,请参阅完整的 :setting:`ALLOWED_HOSTS` 文档。

警告

本文档的先前版本建议配置您的 Web 服务器以确保它验证传入的 HTTP Host 标头。 虽然这仍然是推荐的,但在许多常见的 Web 服务器中,似乎验证 Host 标头的配置实际上可能不会这样做。 例如,即使 Apache 配置为从设置了 ServerName 的非默认虚拟主机为您的 Django 站点提供服务,HTTP 请求仍有可能匹配该虚拟主机并提供一个假 [ X222X] 标头。 因此,Django 现在要求您显式设置 :setting:`ALLOWED_HOSTS` 而不是依赖 Web 服务器配置。


此外,如果您的配置需要,Django 要求您显式启用对 X-Forwarded-Host 标头的支持(通过 :setting:`USE_X_FORWARDED_HOST` 设置)。


推荐人政策

浏览器使用 Referer 标头作为向站点发送有关用户如何到达那里的信息的一种方式。 通过设置 Referrer Policy,您可以帮助保护用户的隐私,限制在何种情况下设置 Referer 标头。 有关详细信息,请参阅安全中间件参考 引用策略部分。


会话安全

类似于 CSRF 限制 要求部署站点以使不受信任的用户无法访问任何子域,django.contrib.sessions 也有限制。 有关详细信息,请参阅 有关安全性的会话主题指南部分


用户上传的内容

笔记

考虑 从云服务或 CDN 提供静态文件以避免其中一些问题。


  • 如果您的站点接受文件上传,强烈建议您在 Web 服务器配置中将这些上传限制为合理的大小,以防止拒绝服务 (DOS) 攻击。 在 Apache 中,这可以使用 LimitRequestBody 指令轻松设置。

  • 如果您正在为自己的静态文件提供服务,请确保禁用像 Apache 的 mod_php 这样将静态文件作为代码执行的处理程序。 您不希望用户能够通过上传和请求特制文件来执行任意代码。

  • 当以不遵循安全最佳实践的方式提供媒体时,Django 的媒体上传处理会带来一些漏洞。 具体来说,如果 HTML 文件包含有效的 PNG 标头和恶意 HTML,则该文件可以作为图像上传。 该文件将通过 Django 用于 ImageField 图像处理(枕头)的库的验证。 当此文件随后显示给用户时,它可能会显示为 HTML,具体取决于 Web 服务器的类型和配置。

    框架级别不存在防弹技术解决方案来安全验证所有用户上传的文件内容,但是,您可以采取一些其他步骤来缓解这些攻击:

    1. 通过始终为来自不同顶级或二级域的用户上传内容提供服务,可以防止一类攻击。 这可以防止任何被 同源策略 保护(例如跨站点脚本)阻止的漏洞利用。 例如,如果您的网站在 example.com 上运行,您可能希望通过 usercontent-example.com 之类的内容提供上传的内容(:setting:`MEDIA_URL` 设置)。 ' 不足以提供来自 usercontent.example.com 等子域的内容。

    2. 除此之外,应用程序可以选择为用户上传的文件定义一个允许的文件扩展名列表,并将 Web 服务器配置为仅提供此类文件。


其他安全主题

虽然 Django 提供了良好的开箱即用的安全保护,但正确部署应用程序并利用 Web 服务器、操作系统和其他组件的安全保护仍然很重要。

  • 确保您的 Python 代码在 Web 服务器的根目录之外。 这将确保您的 Python 代码不会意外作为纯文本(或意外执行)。
  • 小心处理任何 用户上传的文件
  • Django 不会限制对用户进行身份验证的请求。 为了防止对身份验证系统的暴力攻击,您可以考虑部署 Django 插件或 Web 服务器模块来限制这些请求。
  • 将您的 :setting:`SECRET_KEY` 保密。
  • 使用防火墙限制缓存系统和数据库的可访问性是一个好主意。
  • 查看 Open Web Application Security Project (OWASP) Top 10 列表 ,其中确定了 Web 应用程序中的一些常见漏洞。 虽然 Django 有解决一些问题的工具,但在项目设计中必须考虑其他问题。
  • Mozilla 讨论了有关 网络安全 的各种主题。 他们的页面还包括适用于任何系统的安全原则。