【问题标题】:Django won't set HttpOnly for csrftoken cookieDjango 不会为 csrftoken cookie 设置 HttpOnly
【发布时间】:2017-12-04 14:10:08
【问题描述】:

在我的 Django 的 settings.py 中,我有

SESSION_COOKIE_HTTPONLY = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 15768000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SESSION_COOKIE_AGE = 2 * 24 * 3600

但是https://detectify.com 发现没有为 csrftoken cookie 设置此标志。我检查了 Chrome 对 cookie 的说明,如果我理解正确,空 HTTP 列确认这两个 cookie 不是仅 HTTP:

另外,如果我在 chrome 的控制台中执行 document.cookie,则会显示 csrftoken 值。

我想知道为什么会这样。我在 uwsgi 和 nginx 上运行 Django。 nginx配置如下,有问题的站点是https://rodichi.net

server {
    listen 443 ssl http2 default_server;
    server_name rodichi.net;

    ssl_certificate /etc/letsencrypt/live/rodichi.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rodichi.net/privkey.pem;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_ecdh_curve secp384r1;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    charset     utf-8;

    ... # location settings follow here

```

【问题讨论】:

  • 吃掉(删除)你的cookies。至少使用 HTTPonly 正确设置了会话 ID 之一。而你错过了CSRF_COOKIE_HTTPONLY

标签: django nginx cookies httponly


【解决方案1】:

您仅将其配置为将 CSRF 令牌设置为安全(即仅通过 https 请求发送)而不是 HttpOnly(即不适用于 Javascript)。

查看 Django 文档,您还需要设置 CSRF_COOKIE_HTTPONLY。但是文档正确地指出:

将 CSRF cookie 指定为 HttpOnly 并没有任何实际意义 保护,因为 CSRF 只是为了防止跨域 攻击。如果攻击者可以通过 JavaScript 读取 cookie,那么他们就是 就浏览器所知,已经在同一个域上,所以他们可以这样做 反正他们喜欢的任何东西。 (XSS 是一个比 CSRF 大得多的漏洞。)

虽然设置提供的实际好处不大,但有时 安全审计员要求。

这还取决于您如何实施 CSRF。表单基本上有两种方法:

  1. 为每个表单设置一个隐藏的 CSRF 字段,并使该字段在每次加载表单时生成一个唯一值。因此,如果表单提交包含有效代码,那么您就知道该请求来自您的域。这在服务器端很复杂,因为它需要跟踪有效令牌,并且还意味着必须动态生成每个表单以包含随机令牌,但在客户端更容易,因为使用标准表单请求而不是 JavaScript。对于这种保护,不需要 CSRF cookie,即使存在也不使用。

  2. 另一种方法调用设置 CSRF cookie,并让 Javascript 读取它并将其发送到 HTTP 标头(通常是 X-CSRF-TOKEN)中。来自另一个域的 CSRF 请求将无法访问此 CSRF cookie,因此无法正确设置标头。由于 cookie 也将在所有请求上发送,因此服务器很容易检查 HTTP 请求中的 cookie 是否与请求中设置的标头匹配。这意味着请求来自可以访问 cookie 的某个地方,这意味着它来自同一个域。这意味着它不是 CSRF 攻击。这在服务器端更容易实现(因为不需要保留活动令牌列表),但在前端需要 Javascript 并且需要 CSRF 令牌不是 HttpOnly - 正是因为令牌是应该由客户端 Javascript 读取!

再次Django documentation warns against this

如果您启用此功能并需要发送 CSRF 令牌的值 AJAX 请求,您的 JavaScript 必须从隐藏的 页面上的 CSRF 令牌表单输入,而不是来自 cookie。

所以,总而言之,建议为此 cookie 设置 HttpOnly 属性。它限制了你,没有增加真正的保护,并使 cookie 本身毫无意义。

您将在您的网站上突出显示它并在 Pen Test 报告中显示(包括https://detectify.com),但应该接受这一点,因为您认为这是正确的。不确定是否可以在 https://detectify.com 中将此 cookie 列入白名单,这样它就不会每次都发出警报?

【讨论】:

    猜你喜欢
    • 2017-02-04
    • 2011-02-28
    • 2011-04-01
    • 1970-01-01
    • 2016-04-02
    • 2011-02-10
    • 1970-01-01
    • 2016-06-04
    • 2017-01-30
    相关资源
    最近更新 更多