CSRF漏洞跨域携带cookie问题

CSRF漏洞跨域携带cookie问题

1. CSRF漏洞

  用户在登录A网站www.a.com,获取会话凭证sessionid,记录在Cookie
  
  此时用户在同一窗口中打开新标签页网站Bwww.b.com,网站B中含有恶意请求,请求内容为网站A中的接口
  
  在用户打开网站B后,浏览器会自动发起请求,这个时候会自动带上A网站的Cookie
  
  即在用户无感的情况下,完成了一次以用户身份对A网站的恶意请求

2. 什么情况下会发生CSRF

  ①用户会话凭证存放在Cookie
  ②使用Cookie中的会话凭证进行身份认证(有可能Cookie中存放了sessionid值,但是实际身份验证是对Header头中的自定义字段Auth:sessionid进行验证)
  ③后端未校验Referer字段(Referer字段记录HTTP请求源地址)
  ④后端允许跨域请求(非简单请求,OPTIONS请求预检)
  ⑤使用GET请求进行重要操作(增删改查)(http://www.a.com/creat.php?username=123&password=456)(并非只有GET请求会遭受攻击,只是GET请求较容易实现CSRF攻击)

3. CSRF的利用方式

  ①使用HTML标签发送正常跨域请求
  ②通过JS发送请求(CORS策略限制)

4. 实际渗透遇到问题

4.1 同源策略

  同源策略是指两个URL的协议、域名、端口相同的话,那么这两个URL为同源。
  关于同源策略的官方说明
  
  总的来说有以下三点限制:
    1.无法读取非同源网页的 CookieLocalStorageIndexedDB
    2.无法获取非同源网页的 DOM
    3.向非同源地址发送 AJAX 请求浏览器会拒绝响应

4.2 跨域

  根据CSRF攻击的原理来讲,攻击者构造的恶意网站肯定是和要攻击的网站是不同源的,所以这里要考虑的就是跨域的问题了,跨域的方法的话有两种

4.2.1 JSONP跨域

  JSONP利用了scriptiframe等标签的src等属性,这些属性是没有同源策略限制的,从而实现了跨域请求。

  JSONP请求只能使用GET方式发送请求,也就是说如果被攻击的Web应用采用的是GET方式进行操作的话,可以使用JSONP进行CSRF实现,但是在实际操作过程中需要考虑Cookie问题,因为需要Cookie中的字段进行身份验证

  对于JSONP跨域能否携带Cookie的问题,理论上来说使用JSONP进行跨域是不能获取Cookie的,对于浏览器是否会携带跨域请求中对方域的Cookie值,使用三种浏览器进行了测试

  Firefox:携带网站A的Cookie值发起GET请求
  Edge:没有携带网站A的Cookie值发起GET请求
  Chrome:没有携带网站A的Cookie值发起GET请求

  对于这个结果,和下面说到的CORSPOST跨域请求的结果是一样的,应该都是因为SameSite设置导致的。

4.2.2 CORS跨域

  CORS将跨域请求分为两种:简单请求、非简单请求
  满足下图中所有限制的请求即为简单请求,其余的均为非简单请求
  
  在满足简单请求的情况下,浏览器会自动携带Cookie发送跨域请求,也就是说进行身份校验的会话凭证如果存储在Cookie中,并且Web应用中的操作可以用简单请求的方式完成,那么就一定存在CSRF漏洞。
  如果跨域请求为非简单请求,则浏览器会先发送OPTIONS预检请求,后端服务器在接收到OPTIONS请求后,会返回针对实际请求的要求,如果符合要求的话,则会继续发送实际请求,如果不符合的话就不会发送实际请求了。
  下图为实际发送OPTIONS请求,右侧为后端服务器响应信息其中包含了对实际请求的要求

  Access-Control-Request-Method 服务器允许客户端使用POST发起请求
  Access-Control-Request-Headers 服务器允许请求中携带Content-Type字段
  Access-Control-Allow-Origin 服务器允许哪些域发起请求(由于上图中的请求是本地文件目录的HTML发起,如下图所示,所以返回的是null)

  Access-Control-Allow-Credentials 服务器是否允许使用凭证进行实际请求(例如携带Cookie)
  如果实际请求都满足了以上的要求,那么浏览器就会发送实际的请求,但是此时的话并未携带Cookie值来完成CSRF攻击,如果想要实际请求携带Cookie值的话,需要前后端满足以下要求
  后端:
  ①Access-Control-Allow-Credentials字段设置为True
  ②Access-Control-Allow-Origin字段不能设置为*,必须为指定的域名,像上图请求中的null也算是
  前端:
  ①请求要设置withCredentials = true

  在满足上述前后端条件后,浏览器在完成预检请求后会自动携带上Cookie字段,但是由于浏览器的内核特性不同,此时又出现了不同的情况
  Firefox携带网站A的Cookie值发起POST请求
  Edge没有携带网站A的Cookie值发起POST请求
  Chrome没有携带网站A的Cookie值发起POST请求
  测试发现不同的浏览器在同样的前后端配置下,对于Cookie字段的携带产生了不同,于是又产生了以下内容:
  查过资料后发现,Edge和Chrome使用的是同一内核,对于Cookie中的SameSite属性默认是Lax,在这种级别下,具有如下限制

  在这种情况下,想要实现POST跨域请求携带Cookie在Chrome浏览器中是不行的
  测试后发现在将Cookie中的某一字段SameSite属性值手动设置为None(必须先设置字段的Secure属性,否则无效)时

  发送POST跨域请求时,Chrome(Edge)浏览器会自动携带上Cookie中该字段值

  这个就说明了在进行非简单请求时,在满足上文所讲的前后端设置时,是否会自动携带Cookie值在Chrome与Edge浏览器中取决于CookieSameSite字段的值,浏览器默认情况下设置为Lax,如果要手动设置为None的话,必须先设置Secure属性,否则无效。

  本文仅从CSRF攻击者视角出发,记录一下实际渗透过程中遇到的CSRF漏洞利用问题

posted @ 2021-07-26 15:00  Snowieee  阅读(2962)  评论(0编辑  收藏  举报