首先,我假设一个后端控制输入以防止XSS漏洞。
在this answer @Les Hazlewood解释如何在客户端保护JWT。
假设所有通信都有100%TLS - 无论是在期间还是在任何时间 登录后 - 通过基本用户名/密码进行身份验证 验证和接收JWT是一个有效的用例。 这几乎就是OAuth 2的流量之一('密码授权') 作品。 [...]
您只需设置授权标题:
Authorization: Bearer <JWT value here>
但话说,如果您的REST客户端是“不受信任的”(例如, 启用JavaScript的浏览器),我甚至不会这样做:任何值 可通过JavaScript访问的HTTP响应 - 基本上是任何标头 价值或反应的身体价值 - 可以通过嗅探和拦截 MITM XSS攻击。
最好将JWT值存储在仅限安全的http-only cookie中 (cookie config:setSecure(true),setHttpOnly(true))。这保证了 浏览器将:
- 只能通过TLS连接传输cookie,
- 永远不要将cookie值用于JavaScript代码。
醇>这种方法几乎是您为最佳实践所需要做的一切 安全。 最后一件事是确保您拥有CSRF保护 每个HTTP请求,以确保外部域发起请求 到您的网站无法正常运行。
最简单的方法是仅设置安全(但不仅限于http) 具有随机值的cookie,例如一个UUID。
我不明白为什么我们需要具有随机值的cookie,以确保启动对您网站的请求的外部域无法正常运行。对于同源政策,这不是免费的吗?
来自OWASP:
检查原始标题
Origin HTTP Header标准是作为一种方法引入的 防御CSRF和其他跨域攻击。不像 referer,原点将出现在发起的HTTP请求中 来自HTTPS网址。
如果存在原始标题,则应检查它 一致性。
我知道OWASP本身的一般建议是同步器令牌模式,但我看不出剩下的漏洞是什么:
更新1: 同源策略仅适用于XMLHTTPRequest,因此恶意站点可以轻松地生成表单POST请求,这将破坏我的安全性。需要显式的原始标头检查。等式将是:
答案 0 :(得分:14)
摘要
@Bergi,@ Neil McGuigan和@SilverlightFox让我澄清了有关同源策略和CORS的误解概念。
首先,@ Bergi所说的
SOP不会阻止发送请求。它确实阻止了一个页面 访问跨域请求的结果。
是一个重要的概念。我认为浏览器不会根据SOP限制向跨域提出请求,但这仅适用于Monsur Hossain所称的&#34;不那么简单的请求&#34;在this优秀的教程中。
跨域请求有两种形式:
- 简单请求
- &#34;不那么简单的请求&#34; (我刚刚编造的一个词)
简单请求是符合以下条件的请求:
- HTTP方法匹配(区分大小写)以下之一:
- HEAD
- GET
- POST
- HTTP标头匹配(不区分大小写):
- 接受
- 接受语言
- 内容的语言
- 最后-事件ID
- Content-Type,但仅当值为以下值之一时:
- 应用程序/ x-WWW窗体-urlencoded
- 的multipart / form-data的
- 文本/纯
因此,具有内容类型application / x-www-form-urlencoded的POST将命中服务器(这意味着CSRF漏洞),但浏览器将无法访问该请求的结果。 具有内容类型application / json的POST是一个&#34;不那么简单的请求&#34;所以浏览器会发出像这样的预备请求
选项/端点HTTP / 1.1
主持人:https://server.com
连接:保持活力
访问控制请求方法:POST
来源:https://evilsite.com
访问控制请求标题:内容类型
接受:* / *
Accept-Encoding:gzip,deflate,sdch
Accept-Language:es-ES,es; q = 0.8
如果服务器响应,例如:
访问控制 - 允许 - 来源:http://trustedsite.com
访问控制允许方法:GET,POST,PUT
Access-Control-Allow-Headers:内容类型
内容类型:text / html;字符集= UTF-8
浏览器根本不会发出请求,因为
XMLHttpRequest无法加载http://server.com/endpoint。回应 预检请求没有通过访问控制检查: &#39;访问控制允许来源&#39; header包含无效值 &#39; trustedsite.com&#39 ;.起源&#39; evilsite.com&#39;因此不允许访问。
所以我认为Neil在谈到这一点时正在谈论这个:
同源策略仅适用于读取数据而不适用 写它。
然而,由于我向Bergi提议的原始标题显式控制,我认为就此问题而言已经足够了。
关于我对Neil的回答,我并不意味着答案是我所有问题的答案,但它记得我关于SOP的另一个重要问题,那就是该政策仅适用于XMLHTTPRequest&#39; s
总之,我认为方程式
是一个不错的选择。如果客户端位于同一个域中,那么客户端将遇到不包含Origin头的请求的麻烦。再次来自cors tutorial:
Origin标头的存在并不一定意味着 请求是跨域请求。而所有跨源请求 将包含一个Origin标头,一些同源请求可能有 一个也是。例如,Firefox没有包含Origin标头 同源请求。但Chrome和Safari包含一个Origin标头 在同源的POST / PUT / DELETE请求(同源GET请求将 没有Origin标题)。
Silverlight指出this。
唯一的风险是客户端可以欺骗原始标头以匹配允许的来源,所以我正在寻找的答案实际上是this
更新:对于那些观看此帖子的人,我doubts关于是否需要使用JWT的原始标题。
等式将是:
此外,前面的公式有httpOnly cookie,但如果你的客户端和服务器位于不同的域(如今许多SPA应用程序),这将无法工作,因为每次请求都不会发送cookie到服务器。因此,您需要访问存储在cookie中的JWT令牌并将其发送到标题中。
答案 1 :(得分:12)
为什么同源策略不足以阻止CSRF攻击?
因为同源策略仅适用于读取数据而不是写入数据。
您希望避免http://compromised.com
发出此类请求(来自用户的浏览器):
POST https://example.com/transfer-funds
fromAccountId:1
toAccountId:666
合法请求看起来像这样:
POST https://example.com/transfer-funds
fromAccountId: 1
toAccountId: 666
csrfToken: 249f3c20-649b-44de-9866-4ed72170d985
您可以通过要求外部网站无法读取的值(CSRF令牌)来实现此目的,即在HTML表单值或响应标头中。
关于Origin标头,旧浏览器不支持它,而Flash有一些漏洞让客户端更改它。基本上你会相信Adobe不会在将来搞砸任何东西......这听起来像个好主意吗?
确保您对每个HTTP请求都有CSRF保护
您只需要对带有副作用的请求进行CSRF保护,例如更改状态或发送消息
答案 2 :(得分:1)
我只是想总结答案。
ORIGIN
标头以及通过XmlHttpRequests发出的请求。 Chromium
发送origin
。然而,这并不意味着其他浏览器会这样做。下图显示了在Firefox中发出的两个帖子请求。一个是submitting表单,另一个是XHR。这两项请求均来自http://hack:3002/changePassword
到http://bank:3001/chanePassword
。 origin
标头。因此,只有在设置了origin头时,服务器才应检查原始策略。结论是:如果您使用Cookie并且请求在没有origin
标头的情况下发送到服务器,则您无法通过在同一域中提交来自其他域或XHR的表单来区分它。这就是您需要使用CSRF进行额外检查的原因。