为什么同源策略不足以防止CSRF攻击? [英] Why Same-origin policy isn't enough to prevent CSRF attacks?

查看:3691
本文介绍了为什么同源策略不足以防止CSRF攻击?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我假设一个控制输入以防止XSS漏洞的后端。

First of all, I assume a backend that control inputs to prevent XSS vulnerabilities.

In this answer @Les Hazlewood explain how to protect the JWT in the client side.


假设100%的客户端是JWT的客户端, TLS用于所有通信 - 在登录之前和在任何时候
- 用用户名/密码通过基本的
认证进行认证并接收JWT作为交换是有效的用例。
这几乎是OAuth 2的流程('password grant')
的工作原理。
[...]

Assuming 100% TLS for all communication - both during and at all times after login - authenticating with username/password via basic authentication and receiving a JWT in exchange is a valid use case. This is almost exactly how one of OAuth 2's flows ('password grant') works. [...]

您只需设置Authorization标题:

You just set the Authorization header:

Authorization: Bearer <JWT value here>

但是,说的是,如果你的REST客户端是不受信任的启用浏览器),我甚至不会这样做:通过JavaScript可访问的
HTTP响应中的任何值 - 基本上任何标题
值或响应主体值 - 都可以通过$ b被嗅探和拦截$ b MITM XSS攻击。

But, that being said, if your REST client is 'untrusted' (e.g. JavaScript-enabled browser), I wouldn't even do that: any value in the HTTP response that is accessible via JavaScript - basically any header value or response body value - could be sniffed and intercepted via MITM XSS attacks.

最好将JWT值存储在一个安全的,仅限http的cookie
(cookie config:setSecure(true) ,setHttpOnly(true))。这保证
浏览器将:

It's better to store the JWT value in a secure-only, http-only cookie (cookie config: setSecure(true), setHttpOnly(true)). This guarantees that the browser will:


  1. 只通过TLS连接传输Cookie,


  1. only ever transmit the cookie over a TLS connection and,
  2. never make the cookie value available to JavaScript code.

这种方法几乎可以满足JavaScript代码的所有需求。实践
安全。 最后一件事是确保您对每个HTTP请求都有
的CSRF保护,以确保向您的网站发起请求
的外部网域无法运行。

This approach is almost everything you need to do for best-practices security. The last thing is to ensure that you have CSRF protection on every HTTP request to ensure that external domains initiating requests to your site cannot function.

最简单的方法是用一个随机值设置一个安全的(但不是只有http)
cookie,例如一个UUID。

The easiest way to do this is to set a secure only (but NOT http only) cookie with a random value, e.g. a UUID.

我不明白为什么我们需要cookie和随机值,以确保外部域发起请求到您的网站无法正常工作。同源政策不会免费?

I don't understand why we need the cookie with the random value to ensure that external domains initiating requests to your site cannot function. This doesn't come free with Same-origin policy?

OWASP


检查原始标题

Checking The Origin Header

原始HTTP头标准被引入作为
的方法来防御CSRF和其他跨域攻击。与
referer不同的是,HTTP请求中会出现源自HTTPS URL的

The Origin HTTP Header standard was introduced as a method of defending against CSRF and other Cross-Domain attacks. Unlike the referer, the origin will be present in HTTP request that originates from an HTTPS url.

如果存在origin头,应该检查
一致性。

If the origin header is present, then it should be checked for consistency.

我知道OWASP本身的一般建议是Synchronizer Token Pattern,看不清的漏洞:

I know that the general recommendation from OWASP itself is Synchronizer Token Pattern but I can't see what are the vulnerabilities that remains in:


  • TLS + JWT在安全的httpOnly cookie +同源策略+没有XSS漏洞。

UPDATE 1:
同源政策仅适用于 XMLHTTPRequest ,所以一个邪恶的网站可以轻松地做一个表单POST请求,这将打破我的安全。需要显式原始标头检查。方程式为:

UPDATE 1: The same-origin policy only applies to XMLHTTPRequest, so a evil site can make a form POST request easily an this will break my security. An explicit origin header check is needed. The equation would be:


  • TLS + JWT在安全的httpOnly Cookie + 原始标头检查 +没有XSS漏洞。

  • TLS + JWT in secure httpOnly cookie + Origin Header check + No XSS vulnerabilities.

推荐答案

摘要

有关于同源起源政策和CORS的误解概念,@Bergi,@Neil McGuigan和@SilverlightFox帮助我澄清。

I had a misunderstood concepts about Same-origin policy and CORS that @Bergi, @Neil McGuigan and @SilverlightFox helped me to clarify.

首先,@Bergi说


SOP不会阻止发送请求。它确实阻止了
的网页访问跨网域请求的结果。

SOP does not prevent sending requests. It does prevent a page from accessing results of cross-domain requests.

是一个重要的概念。我认为浏览器不会向SOP限制请求交叉域,但这只适用于Monsur Hossain在精彩教程。

is an important concept. I thought that a browser doesn't make the request to the cross domain accordingly to the SOP restriction but this is only true for what Monsur Hossain calls a "not-so-simple requests" in this excellent tutorial.


来源请求有两种风格:

Cross-origin requests come in two flavors:


  • 简单请求

  • 不那么简单请求 (我刚刚编辑的字词)

简单请求是符合以下条件的请求:

Simple requests are requests that meet the following criteria:


  • HTTP方法匹配(区分大小写)以下之一:


    • HEAD

    • GET

    • POST


    • 接受

    • 接受语言

    • 内容语言

    • Last-Event-ID

    • Content-Type,但仅当值为以下之一时:


      • application / x-www-form-urlencoded

      • multipart / form-data

      • text / plain

      • Accept
      • Accept-Language
      • Content-Language
      • Last-Event-ID
      • Content-Type, but only if the value is one of:
        • application/x-www-form-urlencoded
        • multipart/form-data
        • text/plain

        具有内容类型应用程序/ x-www-form-urlencoded的POST将命中服务器(这意味着CSRF漏洞),但浏览器将无法访问该请求的结果。
        使用Content Type应用程序/ json的POST是一个不那么简单的请求,因此浏览器会像这样进行预付费请求

        So, a POST with Content Type application/x-www-form-urlencoded will hit to the server (this means a CSRF vulnerability) but the browser will not make accessible the results from that request. A POST with Content Type application/json is a "not-so-simple request" so the browser will make a prefligth request like this


        OPTIONS / endpoint HTTP / 1.1

        主机:https://server.com

        连接:keep-alive

        访问控制请求方法: POST

        原产地:https://evilsite.com

        访问控制请求标头:内容类型

        接受:* / *

        Accept-Encoding:gzip,deflate,sdch

        Accept-Language:es-ES,es; q = 0.8

        OPTIONS /endpoint HTTP/1.1
        Host: https://server.com
        Connection: keep-alive
        Access-Control-Request-Method: POST
        Origin: https://evilsite.com
        Access-Control-Request-Headers: content-type
        Accept: */*
        Accept-Encoding: gzip, deflate, sdch
        Accept-Language: es-ES,es;q=0.8

        如果服务器响应例如:


        Access-Control-Allow-Origin: http://trustedsite.com

        访问控制 - 允许方法:GET,POST,PUT

        Access-Control-Allow-Headers:content-type

        Content-Type:text / html; charset = utf-8

        Access-Control-Allow-Origin: http://trustedsite.com
        Access-Control-Allow-Methods: GET, POST, PUT
        Access-Control-Allow-Headers: content-type
        Content-Type: text/html; charset=utf-8

        浏览器不会发出请求,因为

        the browser will not make the request at all, because


        XMLHttpRequest无法加载 http://server.com/endpoint。响应
        预检请求不通过访问控制检查:
        'Access-Control-Allow-Origin'头包含无效值
        'trustedsite.com'。因此,不允许访问原始evilsite.com。

        XMLHttpRequest cannot load http://server.com/endpoint. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains the invalid value 'trustedsite.com'. Origin 'evilsite.com' is therefore not allowed access.

        所以我认为Neil在谈论这个问题时指出:

        So I think that Neil was talking about this when he pointed out that:


        同源策略仅适用于读取数据,不适用于
        写入。

        the Same-origin Policy only applies to reading data and not writing it.

        但是,对于我提议给Bergi的origin头显式控制,我认为对于这个问题已经足够了。

        However, with the origin header explicit control that I proposed to Bergi I think is enough with respect to this issue.

        对于我对Neil的回答,我并不是说这个答案是我所有问题的答案,但它记得我关于SOP的另一个重要问题,它的政策只适用于XMLHTTPRequest的。

        With respect to my answer to Neil I didn't mean that that answer was the one to all my question but it remembered me another important issue about SOP and it was that the policy only applies to XMLHTTPRequest's.

        总之,我认为安全的httpOnly cookie + Origin Header检查中的方程式

        In conclusion, I think that the equation


        • TLS + JWT +没有XSS漏洞。

        是一个很好的选择,如果API在另一个领域像SilverlightFox说。如果客户端在同一个域,客户端我会有麻烦的请求,不包括Origin头。再次来自 cors教程

        is a good alternative if the API is in another domain like SilverlightFox says. If the client is in the same domain that the client I will have troubles with requests that doesn't include the Origin header. Again from the cors tutorial:


        Origin头的存在不一定意味着
        请求是跨源请求。虽然所有跨源请求
        将包含一个Origin头,但是一些同源请求也可能有
        。例如,Firefox在
        同源请求中不包括Origin标头。但是Chrome和Safari在同源POST / PUT / DELETE请求中包含一个Origin标头
        (同源GET请求将
        没有Origin标头)。

        The presence of the Origin header does not necessarily mean that the request is a cross-origin request. While all cross-origin requests will contain an Origin header, some same-origin requests might have one as well. For example, Firefox doesn't include an Origin header on same-origin requests. But Chrome and Safari include an Origin header on same-origin POST/PUT/DELETE requests (same-origin GET requests will not have an Origin header).

        Silverlight将引导至。

        Silverlight pointed this out to.

        仍然存在的唯一风险是客户端可以欺骗原始头以匹配允许的来源,因此我正在寻找的答案实际上是 this

        The only risk that remains is that a client can spoof the origin header to match the allowed origin, so the answer i was looking for was actually this

        更新:对于那些观看此信息的人,我对如果使用JWT需要原始标题有疑问

        UPDATE: for those who watch this post, I have doubts about if the origin header is needed at all using JWT.

        方程式为:


        • TLS + JWT存储在安全cookie + JWT请求头+没有XSS漏洞。

        此外,上面的方程有httpOnly cookie,但是如果你得到客户端和服务器在不同的域(如今许多SPA应用程序),因为cookie不会与每个请求一起发送到服务器。因此,您需要访问存储在cookie中的JWT令牌,并将其发送到标头中。

        Also, the previous equation has httpOnly cookie but this won't work if you got the client and the server in different domains (like many SPA application today) because the cookie wouldn't be sent with each request to the server. So you need access the JWT token stored in the cookie and send it in a header.

        这篇关于为什么同源策略不足以防止CSRF攻击?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆