【问题标题】:CSRF protection with JSON Web Tokens使用 JSON Web 令牌进行 CSRF 保护
【发布时间】:2016-05-19 09:50:30
【问题描述】:

我读到在使用 JWT 时,不需要防范 CSRF 攻击,例如:“since you are not relying on cookies, you don't need to protect against cross site requests”。

但是,我不明白的一点是:如果我将令牌存储在 localStorage 中(正如我被告知的 on a tutorial of the same website),什么可以防止攻击者通过读取我的 localStorage 而不是我的 cookie 来伪造恶意请求?

由于它是在服务器端生成的,我不明白如何在不将令牌存储在客户端某处的情况下将其用于客户端请求。

【问题讨论】:

    标签: local-storage csrf jwt auth0


    【解决方案1】:

    严格来说,是的,存储在本地/会话存储(我称之为 HTML5 存储)中的任何内容都可能在跨站点脚本 (XSS) 攻击中被盗。见this article

    但是,有很多活动部件需要考虑。

    首先,就 JavaScript 访问而言,HTML5 存储和 cookie 的范围存在细微差别。

    HTML5 存储是:

    • 分为http和https。 https://example.com 上运行的 JavaScript 无法访问存储在 http://example.com HTML5 存储中的项目。
    • 在子域之间划分。在http://sub.example.com 上运行的JavaScript 无法访问存储在http://example.com HTML5 存储中的项目(不过,您可以通过tricks 来解决这个问题)。

    Cookie 比较松散:

    • 域为example.com 的cookie 将同时发送到http://example.comhttps://example.com 除非它具有secure 属性,在这种情况下它只会发送到https .
    • 未使用显式域发送的 cookie 只会被发送回发送它的确切域。如果域被明确定义为example.com,那么它将被发送到example.comsub.example.com。 (不幸的是,这是 cookie“规范”中最令人困惑的部分,请参阅 this article)。
    • 如果 cookie 在具有匹配域的页面上运行(并且尊重 secure cookie 标志),则 JavaScript 可以读取 cookie 除非 cookie 具有 httpOnly 属性,其中case JavaScript 将无法读取它。

    其次,由于 cookie 带有域标记,因此当向服务器发出请求时,浏览器将发送具有匹配域的全部和唯一的 cookie,无论发起该页面的域是什么请求

    最后一部分是 CSRF 攻击是如何完成的(同源策略只能起到这么大的作用)。 OWASP page on CSRF 是了解此类攻击如何工作的好资源。

    在本地存储中存储身份验证令牌并手动将其添加到每个请求以防止 CSRF 的原因是关键字:手动。由于浏览器不会自动发送该身份验证令牌,如果我访问evil.com 并且它设法发送POST http://example.com/delete-my-account,它将无法发送我的身份验证令牌,因此该请求将被忽略。

    考虑到上述情况,是使用 cookie 还是使用 HTML5 存储成为一系列权衡:

    在 HTML5 存储中存储 authen 令牌意味着:

    • (-) 在 XSS 攻击中被盗的风险。
    • (+) 提供 CSRF 保护。
    • (-) 必须手动修改发往服务器的每个请求,将您限制为 SPA(例如 AngularJs)Web 应用程序。

    另一方面,如果您将身份验证令牌存储在标记为httpOnly secure 的cookie 中,那么:

    • (+) Authn 令牌不能被 XSS 窃取。
    • (-) 你必须自己提供 CSRF 保护。在某些框架中实施 CSRF 保护比在其他框架中更容易。

    哪个选项更好取决于您的需求。

    • 您的身份验证令牌是否保护与金钱有关的任何事情?您可能需要 cookie httpOnly secure 选项。
    • 实施 CSRF 保护所需的努力程度是否不值得其保护的资产?那么 HTML5 存储可能是正确的地方。

    【讨论】:

    • 出色的答案。我现在比以往任何时候都更害怕。是时候仔细检查我应用中的每个文本输入字段了。
    • 首先,同源可以防止读取/查看数据,但不能防止提交请求。有错请指正。
    • @Zack evil.com 无法访问 example.com 的 Web 存储或 cookie,因此 evil.com 无法获得有效的 auth/CSRF 令牌。但是,对于所有请求,cookie 都会自动提交到服务器,即使它们是从 evil.com 发送的。如果您的会话令牌是 cookie,您还需要提供 CSRF 令牌。但是,如果您的会话令牌在本地存储中,您必须“手动”将其添加到每个请求中,浏览器不会为您执行此操作。如果 Javascript 将令牌添加为自定义标头,那就更好了,因为 SOP 不允许使用自定义标头的跨源请求。
    • @Zack 但是,我不确定这有多实用,因为单击您网站上另一个页面的简单链接不会在单击时发送会话令牌。这就是我试图通过说您仅限于“SPA(例如 AngularJs)Web 应用程序”来表达的意思。我不能 100% 确定链接问题的解决方法是什么。
    • @Zack 在 evil.com 上运行的 JavaScript 如何访问 example.com 的 Web 存储?这不可以。 Web 存储规范讨论了为什么每个域的 Web 存储必须是私有的,w3.org/TR/webstorage/#implementation-risks。当您说“WebStorage 将愉快地通过 HTTP 发回流量”时,我不明白您的意思,Web 存储不发送或接收 http 请求。与我原来的答案类似,这里有一篇文章谈论使用网络存储来存储会话 cookie,blog.portswigger.net/2016/05/…
    【解决方案2】:

    使用基于令牌的身份验证时,您必须手动将令牌与请求相关联。与 cookie 不同,令牌不是由浏览器自动设置的,因此不易受到 csrf 攻击。

    虽然这种方法可以避免csrf 攻击,但它很容易受到xss 攻击。

    最小的改进是使用session storage 而不是local storage,因为session storage 数据在用户关闭选项卡/浏览器后被清除。

    【讨论】:

      猜你喜欢
      • 2013-03-27
      • 2013-07-20
      • 2016-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-23
      • 2014-09-01
      • 2011-09-07
      相关资源
      最近更新 更多