Django 的安全性

此文档是对 Django 安全性特征的概述。它包含了对保障使用 Django 驱动的网页安全的建议。

防御跨站脚本攻击(XSS)

XSS 攻击让其使用者可以向其他用户的浏览器中注入客户端脚本。它通常由在数据库中存储恶意脚本的方式来实现,这些脚本会在数据库中被检索并显示给其他用户;或通过用户点击那些会引发攻击者的 JavaScript 脚本被用户浏览器执行的链接来实现。然而,倘若在数据加载到页面之前未经过彻底的清理,那么 XSS 攻击可以来自任何不可信任的数据源,比如 cookies 或者 Web 服务器。

使用 Django 的模板可以保护您免受大多数XSS攻击。但是了解它提供了怎样的保护,以及有什么限制等是很重要的。

Django 模板 escape specific characters 对于 HTML 来说是很危险的。这保护着用户免受多数恶意输入的攻击,但并非万无一失。比如,出现下面这种情况就会保护失效:

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

如果 var 被设置为 'class1 onmouseover=javascript:func()' ,将导致未经授权的 JavaScript 脚本执行,这取决于浏览器如何呈现不完美的HTML。(引用属性值可以解决这个问题)

同样重要的,还有在 is_safe 与自定义模板标签,safe 模板标签,mark_safe 一起设置时,以及关闭自动转义时要特别小心。

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

您在将 HTML 储存到数据库中时也要非常小心,特别是在检索和显示 HTML 的时候。

防御跨站点请求伪造(CSRF)

CSRF 攻击让恶意用户可以使用别的用户的证书执行操作,且是在其不知情或不同意的情况下。

Django 已经内置了保护措施来对抗大多数 CSRF 攻击,您需要在合适的地方 enabled and used it 。但和多数缓解性技术一样,它是有局限性的。比如可以全局禁用 CSRF 模块或者特定的视图。如果您真的想这么做,请三思而后行。如果您的网页还有脱离您控制的子域,还将会有其他 limitations

CSRF 保护机制 通过检查每一个 POST 请求中的密文来实现。这保证恶意用户不能“复现”一个表单并用 POST 提交到你的网页,并让一个已登录用户无意中提交该表单。恶意用户必须知道特定于用户的密文(使用 cookie)。

在部署 HTTPS 时,CsrfViewMiddleware 会检查 HTTP 报文的 referer 首部是否设置为同源的 URL(包括子域和端口)。因为 HTTPS 提供了额外的安全性,所有通过转发不安全连接请求并在支持的浏览器中使用 HSTS 来确保连接在可用的地方使用了 HTTPS ,这一点是很重要的。

除非绝对需要,否则对视图进行标记 csrf_exempt 装饰器时要极其慎重。

防御 SQL 注入

SQL 注入是一种让恶意用户能在数据库中执行任意 SQL 代码的攻击方式。这将导致记录被删除或泄露。

Django 的 querysets 在被参数化查询构建出来时就被保护而免于 SQL 注入。查询的 SQL 代码与查询的参数是分开定义的。参数可能来自用户从而不安全,因此它们由底层数据库引擎进行转义。

Django 也为开发者提供了书写 raw queries 或执行 custom sql 的权利。应当尽可能少地使用这些方法,并且您应该小心并准确的转义一切用户可控的参数。另外,在使用 extra()RawSQL 时应当小心谨慎。

防御访问劫持

访问劫持是一种让恶意网页能覆盖另一个网页框架的攻击方式。这将导致毫不知情的用户被骗入目标网页并执行意料之外的操作。

Django 包含 clickjacking protection ,以 X-Frame-Options middleware 的形式在支持它的浏览器中阻止一个网页被渲染在 frame 的内部。可在每个视图的基础上禁用保护,也可配置发送的确切头部值。

对于任何不会被第三方网站嵌入 frame 的网页,或者只允许使用一小部分的网页来说,强烈建议使用中间件。

SSL/HTTPS

将您的网页通过 HTTPS 部署,对于保障安全性来说是最佳的。没有它,恶意网络用户就可以在客户端和服务器之间嗅探验证资格或其他任何信息,在某些情况下 -- 主动 网络攻击者 -- 会修改发向其中任何一方的数据。

如果您想得到 HTTPS 的保护,且已经在您的服务器上启用了,下面还有一些额外的步骤需要执行:

  • 如果有必要,设置 SECURE_PROXY_SSL_HEADER,确保您已经彻底的了解了它的警告。如果不这么做,将会导致 CSRF 漏洞,如果操作不正确,也是非常危险的。

  • 设置 SECURE_SSL_REDIRECTTrue,这样 HTTP 的请求就会被重定向到 HTTPS。

    请注意 SECURE_PROXY_SSL_HEADER 下的警告。对于反向代理,设置主服务器来重定向到 HTTPS 会更简单且更安全。

  • Use 'secure' cookies.

    If a browser connects initially via HTTP, which is the default for most browsers, it is possible for existing cookies to be leaked. For this reason, you should set your SESSION_COOKIE_SECURE and CSRF_COOKIE_SECURE settings to True. This instructs the browser to only send these cookies over HTTPS connections. Note that this will mean that sessions will not work over HTTP, and the CSRF protection will prevent any POST data being accepted over HTTP (which will be fine if you are redirecting all HTTP traffic to HTTPS).

  • Use HTTP Strict Transport Security (HSTS)

    HSTS is an HTTP header that informs a browser that all future connections to a particular site should always use HTTPS. Combined with redirecting requests over HTTP to HTTPS, this will ensure that connections always enjoy the added security of SSL provided one successful connection has occurred. HSTS may either be configured with SECURE_HSTS_SECONDS, SECURE_HSTS_INCLUDE_SUBDOMAINS, and SECURE_HSTS_PRELOAD, or on the Web server.

Host header validation

Django uses the Host header provided by the client to construct URLs in certain cases. While these values are sanitized to prevent Cross Site Scripting attacks, a fake Host value can be used for Cross-Site Request Forgery, cache poisoning attacks, and poisoning links in emails.

Because even seemingly-secure web server configurations are susceptible to fake Host headers, Django validates Host headers against the ALLOWED_HOSTS setting in the django.http.HttpRequest.get_host() method.

This validation only applies via get_host(); if your code accesses the Host header directly from request.META you are bypassing this security protection.

For more details see the full ALLOWED_HOSTS documentation.

警告

Previous versions of this document recommended configuring your web server to ensure it validates incoming HTTP Host headers. While this is still recommended, in many common web servers a configuration that seems to validate the Host header may not in fact do so. For instance, even if Apache is configured such that your Django site is served from a non-default virtual host with the ServerName set, it is still possible for an HTTP request to match this virtual host and supply a fake Host header. Thus, Django now requires that you set ALLOWED_HOSTS explicitly rather than relying on web server configuration.

Additionally, Django requires you to explicitly enable support for the X-Forwarded-Host header (via the USE_X_FORWARDED_HOST setting) if your configuration requires it.

Referrer policy

Browsers use the Referer header as a way to send information to a site about how users got there. By setting a Referrer Policy you can help to protect the privacy of your users, restricting under which circumstances the Referer header is set. See the referrer policy section of the security middleware reference for details.

会话安全

Similar to the CSRF limitations requiring a site to be deployed such that untrusted users don't have access to any subdomains, django.contrib.sessions also has limitations. See the session topic guide section on security for details.

User-uploaded content

注解

Consider serving static files from a cloud service or CDN to avoid some of these issues.

  • If your site accepts file uploads, it is strongly advised that you limit these uploads in your Web server configuration to a reasonable size in order to prevent denial of service (DOS) attacks. In Apache, this can be easily set using the LimitRequestBody directive.

  • If you are serving your own static files, be sure that handlers like Apache's mod_php, which would execute static files as code, are disabled. You don't want users to be able to execute arbitrary code by uploading and requesting a specially crafted file.

  • Django's media upload handling poses some vulnerabilities when that media is served in ways that do not follow security best practices. Specifically, an HTML file can be uploaded as an image if that file contains a valid PNG header followed by malicious HTML. This file will pass verification of the library that Django uses for ImageField image processing (Pillow). When this file is subsequently displayed to a user, it may be displayed as HTML depending on the type and configuration of your web server.

    No bulletproof technical solution exists at the framework level to safely validate all user uploaded file content, however, there are some other steps you can take to mitigate these attacks:

    1. One class of attacks can be prevented by always serving user uploaded content from a distinct top-level or second-level domain. This prevents any exploit blocked by same-origin policy protections such as cross site scripting. For example, if your site runs on example.com, you would want to serve uploaded content (the MEDIA_URL setting) from something like usercontent-example.com. It's not sufficient to serve content from a subdomain like usercontent.example.com.
    2. Beyond this, applications may choose to define a list of allowable file extensions for user uploaded files and configure the web server to only serve such files.

Additional security topics

While Django provides good security protection out of the box, it is still important to properly deploy your application and take advantage of the security protection of the Web server, operating system and other components.

  • Make sure that your Python code is outside of the Web server's root. This will ensure that your Python code is not accidentally served as plain text (or accidentally executed).
  • Take care with any user uploaded files.
  • Django does not throttle requests to authenticate users. To protect against brute-force attacks against the authentication system, you may consider deploying a Django plugin or Web server module to throttle these requests.
  • Keep your SECRET_KEY a secret.
  • It is a good idea to limit the accessibility of your caching system and database using a firewall.
  • Take a look at the Open Web Application Security Project (OWASP) Top 10 list which identifies some common vulnerabilities in web applications. While Django has tools to address some of the issues, other issues must be accounted for in the design of your project.
  • Mozilla discusses various topics regarding web security. Their pages also include security principles that apply to any system.