CORS Lite
Dakota Nelson//
跨域资源共享(CORS)非常复杂,这种复杂性导致了许多安全漏洞可能潜入的地方。本文将为您提供一个“轻量级”的CORS概述,重点关注我们在测试中最常见的安全漏洞。这并非完整的CORS入门指南——如果您有兴趣深入探讨,文末有一个资源部分可以帮助您入门。
CORS有许多方面,因此让我们逐一介绍几个更常见的情况,看看可能出什么问题。
CORS规范中最基本的部分是“Access-Control-Allow-Origin”头部,这是构建一切的基础。此头部告知浏览器允许哪些源访问特定资源。换句话说,如果您的Web应用程序中的JavaScript(用户的浏览器从app.example.com加载)向api.example.com发出请求,则该请求是跨域的,默认情况下将被拒绝(即浏览器不会发出请求,或会忽略请求结果),除非api.example.com返回一个“Access-Control-Allow-Origin”头部,告诉浏览器这是可以的。
在以下所有图像中,大的绿色竖起大拇指表示场景成功并发生,大的红色竖起大拇指表示浏览器拒绝执行场景(尽管可能直到中途才拒绝——CORS很复杂,我在这里略过了一些内容)。
对于像API这样的东西,Access-Control-Allow-Origin头部通常设置为“*”,这允许任何域向API发出跨域请求。这意味着任何地方的任何JavaScript都可以访问您的API。但幸运的是,即使有Access-Control-Allow-Origin头部,跨域请求也不会传输cookie或其他认证材料,因此这个头部本身实际上是相当安全的。
Access-Control-Allow-Origin头部通常不会单独引发安全问题,但当它被添加时,它可能使其他问题变得更糟。
最大的风险来自另一个CORS头部的添加:Access-Control-Allow-Credentials。当返回此头部时,跨域请求被允许包含cookie和其他认证材料。这就是问题真正开始的地方。如果用户访问example.com,并且example.com在他们的浏览器中设置了一个cookie(例如,在他们登录后),Access-Control-Allow-Credentials头部将允许该cookie由同一浏览器从其他域发出的请求发送。这意味着这些域可以使用由example.com设置的cookie在example.com上执行操作,无论谁控制这些域上运行的JavaScript!
如果对example.com的请求返回一个Access-Control-Allow-Origin: foo.bar头部和一个Access-Control-Allow-Credentials: true头部,那么foo.bar上的任何脚本都像它们是example.com上的本地脚本一样具有特权执行。这意味着foo.bar上的XSS漏洞等同于example.com上的XSS漏洞!如果您是example.com的所有者,这是对另一个站点所有者的极大信任,您应该在这样做之前非常仔细地考虑。
由于Access-Control-Allow-Credentials头部非常危险,因此有一些保护措施来防止意外。首先,它不能与Access-Control-Allow-Origin: *结合使用。一些站点通过简单地在响应中反射回Origin头部中发送的内容到Access-Control-Allow-Origin头部来绕过此限制。如果您曾经考虑这样做,请在这样做之前非常仔细地考虑您所承担的风险。Access-Control-Allow-Credentials头部的另一个限制是在客户端——XMLHttpRequests必须故意设置一个“withCredentials”标志,以请求发送凭据,确保您绝对希望浏览器在跨域请求中发送cookie和其他敏感材料。
这些保护措施有些令人困惑,因此我在下面设置了一个网格,显示您可能遇到的不同场景。
在左侧,您可以看到服务器返回的头部,而在顶部,您可以看到客户端JavaScript是否设置了“withCredentials”标志。任何红色框表示请求被浏览器完全拒绝——例如,前两行完全是红色的,因为没有Access-Control-Allow-Origin头部,跨域请求是不允许的。在框本身中,您可以看到客户端是否发送了cookie。如果您想进一步玩弄这个并查看创建此网格的确切代码,您可以自己运行此示例——从Github获取:https://github.com/DakotaNelson/cors-test-server。
但这里的主要要点是:如果您将Origin头部反射到您的Access-Control-Allow-Origin头部,并同时设置Access-Control-Allow-Credentials: true,那么任何能够在您的用户浏览器中执行恶意JavaScript的攻击者,无论该JavaScript在哪里,都可以劫持该用户由您的应用程序设置的cookie,并以该用户的身份行事。如果他们常访问的站点中存在XSS漏洞,攻击者能够在针对他们的广告中执行JavaScript,或者攻击者在网络钓鱼用户到攻击者控制的页面后执行JavaScript,如果该用户在您的应用程序上有会话,那就游戏结束了。
一些应用程序试图折中,手动验证origin头部而不是仅仅反射它——因此,例如,任何匹配“*.example.com”的内容被认为是“安全的”,并将在Access-Control-Allow-Origin头部中返回。
您看到这里的问题了吗?能够说服用户访问“example.com.malicious.com”(可能通过网络钓鱼)的攻击者可以进行与以前相同的攻击,因为该站点匹配模式!这仍然比在Access-Control-Allow-Origin头部中反射回任何任意源更好,但一如既往,验证非常棘手,难以正确完成。
CORS还有其他曲折和我们未涵盖的头部,但您需要理解的关键是:CORS很复杂,任何时候您考虑用它做任何事情,都值得研究其影响。下面的资源是我在理解CORS的安全影响时发现有用的东西,如果您是动手型,您绝对应该设置CORS测试服务器并摆弄一段时间,以帮助您理解发生了什么。
祝您好运,希望您喜欢这个CORS轻量指南!
其他资源: