防范 CSRF 和 XSS(散列 + 加密)

Ani*_*kar 5 xss rest csrf

安全。如今,如果没有通过开发人员使用的框架或开发人员自己编程适当的安全性,任何应用程序都无法在互联网上生存。我目前正在开发一个 RESTful API,以使用 Bearer 令牌身份验证进行工作,但一直在阅读有关 XSS 和 CSRF 攻击的内容。

问题 1)从我所读到的内容来看,如果令牌存储在浏览器的 localStorage/sessionStorage 而不是 cookie 中,则使用基于令牌的身份验证的 RESTful API 的应用程序容易受到 XSS 而不是CSRF的攻击。这是因为,要使 CSRF 发挥作用,应用程序必须使用 cookie。我对么?

但现在令牌存储在 localStorage/sessionStorage 中,应用程序变得容易受到 XSS 攻击。如果应用程序的任何部分不清理输入(例如,框架对 Angular 输入进行清理,但也许我正在使用的某个第三方库默认情况下不清理输入),那么攻击者就可以注入恶意代码窃取其他用户的令牌,然后通过模拟他们发出经过身份验证的请求。

问题 2)有一种方法可以在使用 RESTful API 的应用程序中防范这两种攻击。我偶然发现了这篇文章。该文章的要点是,在用户登录并请求不记名令牌时,让服务器也返回一个httpOnlycookie,该 cookie 的作用类似于CSRFProtectionCookie. 我相信本文中的解决方案非常强大并且提供了强大的保护。再说一遍,我说得对吗?您有何看法?

我的应用程序和我在上面的帖子中提到的方法的版本

上面的帖子中提到的方法要求我将其保存CSRFProtectionCookie在某种数据库中。我不想那样做。我不希望每次向 API 发出经过身份验证的请求时都会访问数据库。相反,我能做的是:

登录

  1. 用户使用用户名和密码向令牌端点发送 POST 请求
  2. 授权服务器验证用户凭据并开始使用某些声明构建 JWT。
  3. 作为 JWT 构建的一部分,它还生成一个随机字符串,对其进行哈希处理,然后将其添加csrf为 JWT 的声明。
  4. 另外,接下来服务器设置一个httpOnly名为 的 cookie XSRF-TOKEN,其值是相同的随机字符串,但这次是加密的。
  5. 将响应返回给浏览器。浏览器获取不记名令牌作为响应正文并XSRF-TOKEN设置 cookie。

经过身份验证的请求

  1. 应用程序通过添加 JWT 不记名令牌作为Authorization标头来调用经过身份验证的端点。浏览器自动发送 cookie。

  2. 服务器解密cookie以获取纯文本。然后,服务器使用 JWT 中存在的哈希值验证该纯文本。

  3. 如果匹配,则继续请求。否则,返回未经授权的响应。

我认为这可以防止 CSRF 和 XSS。因为发出经过身份验证的请求都需要令牌和 cookie (httpOnly)。

问题是的,这消除了将任何内容保存到数据库的需要(或者是吗?我是否遗漏了一些漏洞?)。但是,在每个用户请求上解密和验证哈希值的开销是多少?是否比数据库 I/O 开销更大?另外,欢迎对此方法或其他方法提出任何其他建议!

谢谢 :)

Sil*_*Fox 2

如果您使用承载身份验证,则任何攻击者都无法进行 CSRF,因为他们没有令牌值。它不会被浏览器自动添加到请求中,因此它本质上是安全的,可以防止 CSRF。请参阅此处了解 CSRF 的说明以及自定义标头如何缓解它。承载身份验证以相同的方式解决问题,因为在未启用 CORS 的情况下无法添加自定义标头,或者如果 CORS 处于活动状态(这对于 API 来说很常见),则由于针对 API 的身份验证是通过令牌值本身实现的,因此任何攻击者不会知道要提供的值(如果他们知道,他们只会直接使用该值而不需要 CSRF),并且浏览器不会像基本身份验证、摘要等、cookie 身份验证或证书那样自动提供身份验证验证。

为了防止 XSS(这是一个不同的问题),请确保所有 HTML 输出都经过 HTML 编码(>变为>)。如果 API 输出格式化的 HTML,则可以在 API 本身中完成此操作;如果由消费者来适当格式化输出,则可以在 JavaScript 中完成此操作。JavaScript 和 JQuery 等框架中内置的函数也可以提供帮助(例如 textContenttext())。