错误配置CORS的3种利用方法

0x00 概要

在Web环境中,同源策略(SOP)可以限制不同应用之间的信息共享,只允许托管在特定域内应用的信息共享,这是防止系统泄露敏感信息的一种预防措施。然而,随着Web应用和微服务使用场景的不断拓展,在实际环境中人们的确需要将信息从一个子域(subdomain)传输到另一个子域,或者在不同域之间传输信息。为了实现页面渲染和关键功能,人们可能存在这种需求,例如将访问令牌及会话标识符传递给另一个应用就是典型的使用场景。

在部署SOP的情况下,为了实现跨域通信,开发人员必须使用不同的技术来绕过SOP,以便传递敏感信息。这种“绕过”发生了太多次,本身已经成为一个安全问题。因此,为了在不影响应用程序安全状态的前提下实现信息共享,HTML5中引入了跨域资源共享(CORS)这种机制,但这并没有解决所有问题。当人们想偷工减料,或者没有意识到潜在风险而开始使用默认配置或者错误配置的CORS时,就会出现一些问题。

因此,作为安全分析人员或者工程师,我们必须理解错误配置的CORS头部会导致什么问题,这一点非常重要。事实上,攻击者可能利用错误配置的CORS头部来窃取数据,或者入侵整个目标应用。了解相关风险后,我们就可以在灾难发生之前及时修复安全短板。

0x01 CORS简介

跨域资源共享(Cross-Origin Resource Sharing,简称为CORS)是能够帮助Web浏览器以受控方式使用XMLHttpRequest API执行跨域请求的一种机制。这种跨域请求中包含一个Origin头,可以用来标识发起该请求的所属域。CORS定义了在Web浏览器和服务端之间使用的一种协议,可以确定是否允许跨域请求。

0x02 CORS关键头部

有许多HTTP头部与CORS有关,其中在安全方面最为关键的3个响应头如下所示:

  • Access-Control-Allow-Origin:指定哪些域可以访问当前域资源。比如,如果requester.com想访问provider.com的资源,那么开发者可以使用这个头部来安全地授予requester.comprovider.com相关资源的访问权限。
  • Access-Control-Allow-Credentials:指定浏览器是否在请求中发送cookie。只有allow-credentials头部的值为true,浏览器才会发送cookie。
  • Access-Control-Allow-Methods:指定可以使用哪些HTTP请求方法(如GETPUTDELETE等)来访问资源。开发者可以利用该头部来指定requester.com请求provider.com资源时所使用的具体方法,进一步加强安全性。

0x03 三种攻击场景

利用CORS头部中错误配置的通配符(*)

最常见的一种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

在这个例子中,头部字段中包含一个通配符(*),这意味着任何域都可以访问目标资源。

在测试客户的某个应用时,我们注意到该应用存在这种错误配置问题,我们也利用这一点获取到了用户的敏感信息,包括姓名、User ID、Email ID等,最终成功将这些信息发送到外部服务器。在下图中,我们修改了请求的Origin头,把www.victim.com修改成攻击者所在的域。

图1. 修改请求中的Origin

我们收到的响应如下图所示,响应头中包含Access-Control-Allow-Origin: *,这意味着所有站点都可以访问victim域的资源。在这个攻击场景中,我们使用的是testing.aaa.com这个站点。

图2. 响应数据

由于目标站点可以与任何站点共享信息,因此我们使用自己的域进一步利用这一点。我们创建了名为https://testing.aaa.com的一个域,然后在该域中嵌入了利用代码,以便从存在缺陷的目标应用窃取敏感信息。当受害者在浏览器中打开https://testing.aaa.com时,利用代码就可以获取敏感信息,将其发送到攻击者的服务器。使用这种攻击方法我们能够获取到的信息如下图所示:

图3. 应用将敏感信息发送给攻击者

利用错误匹配的不完整域名

另一种常见的错误配置就是允许非完整域名之间的信息共享。比如,考虑如下一种请求:

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头部的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. 修改请求中的Origin字段值

响应数据如下所示,其中Access-control-Allow-Origin照搬了我们设置的Origin头,这意味着以requester.com结尾的域能够访问provider.com域上的资源。

图5. 响应头

我们可以采用与第一种错误配置场景类似的利用方式。比如,我们可以创建包含白名单域名的一个新域名,然后在该恶意站点中嵌入利用代码。以便从受害站点中窃取敏感信息。

使用XSS请求跨域站点

为了防御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漏洞。那么用户就能通过跨站脚本攻击来攻击provider.com

为了演示这种攻击方法,我们在同一个域中托管了两个应用。目标CORS应用托管于testingcors.com上,另一个应用托管于pavan.testingcors.com上,并且后者存在跨站脚本问题。

图6. pavan.testingcors.com存在XSS漏洞

利用存在XSS漏洞的这个子域,我们可以窃取testingcors.com上的敏感信息。我们在Name参数中注入了恶意javascript payload。当该页面加载时,脚本就会执行,获取testingcors.com上的敏感信息。

图7. 利用XSS攻击获取敏感信息

0x04 总结

CORS是名列OWASP TOP 10的一个安全性错误配置问题。在站点之间共享信息时,人们通常会忽视CORS配置的重要性。作为开发者或者安全专家,我们需要了解这种漏洞的背后原因和利用方式,这一点非常重要。

原文:https://www.we45.com/blog/3-ways-to-exploit-misconfigured-cross-origin-resource-sharing-cors

点击收藏 | 1 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖