CORS跨域漏洞详解
[TOC]
域
在前端中,“域”是由以下三个部分共同组成的:
| 组成部分 | 举例 |
|---|---|
| 协议(protocol) | http://或https:// |
| 主机(hostname/域名) | www.example.com,api.example.com |
| 端口(port) | 80、443、8080等 |
简单来说:Origin(域) = 协议 + 域名 + 端口
同源策略(SOP)
同源策略是浏览器的一种安全机制,它限制一个源的js脚本对另一个源的访问。
浏览器的同源策略规定:不同域的客户端脚本在没有明确授权的情况下,不能读写对方的资源。
同源指三个部分相等,即协议,域名和端口,三者有一个不同即视为不同源
简单来说:在浏览器中,只有当协议、域名、端口相同的情况下,才能读写对方的dom、cookie、session、ajax等操作的权限资源。
跨源资源共享(CORS)
CORS的出现是用来弥补SOP(同源策略)的不足。
在当时SOP有些限制了网页的业务需求,不能够使不同域的网页互相访问,因此提出了CORS:用于绕过SOP(同源策略)来实现跨域资源访问的一种技术。(CORS使用自定义的HTTP头部让浏览器与服务器进行沟通,它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服AJAX只能同源使用的限制。)
同源策略用来限制一个网站对不同源网站的访问,但是如果有一个网站要对信任的不同源站点进行访问,同源策略就是造成妨碍。
CORS是放宽同源策略的一套机制,它通过使用一套HTTP请求来实现
常用CORS请求头
● Origin和Access-Control-Allow-Origin:响应的和请求头的Origin必须对得上,才能够访问响应。当Access-Control-Allow-Origin字段值为‘*’时,就代表任意域都可以访问。
● Access-Control-Allow-Credentials:Boolean 如果请求包含如cookie,authorization headers等认证信息时,是否允许读取响应
●Access-Control-Allow-Methods: PUT, POST, OPTIONS 限制请求方法
● Access-Control-Allow-Headers: Special-Request-Header 请求需要包含特点头部
● Access-Control-Max-Age 预检请求的结果可以被缓存多久
CORS跨域漏洞
概述
CORS跨域漏洞的本质是服务器配置不当
即Access-Control-Allow-Origin取自请求头Origin字段,Access-Control-Allow-Credentials设置为true。
导致攻击者可以构造恶意的脚本 , 诱导用户点击获取用户敏感数据
CORS请求可分为两类,简单请求和非简单请求。
漏洞原理
浏览器直接发出CORS请求,接下来浏览器会自动在请求的header中加上Origin字段,告诉服务器这个请求来自哪个源。
1 | Origin: |
服务器端收到请求后,会对比这个字段,如果这个源在服务器端的许可范围内,服务器的响应头会加上以下字段
1 | Access-Control-Allow-Origin:(这里的值为Origin的值) |
如果说服务端配置了 Access-Control-Allow-Origin 响应头,并且浏览器认可该值,跨域就被允许了,此时漏洞也产生了
验证方式
只需要在header中添加以下内容即可验证
1 | Origin: foo.example.org |
然后返回值携带以下,就能证明存在跨域漏洞。
1 | Access-Control-Allow-Origin: foo.example.org |
不存在漏洞情况
如果有下面的情况可以说基本不存在CORS,除非你删除掉参数后依然能够得到响应,那说明上面的参数是一个无效参数也就是一个摆设。
- 响应包中的Access-Control-Allow-Origin值一直为*,不随着请求包中的origin改变。组合如下,因为浏览器会阻止如下的配置:
1 | Access-Control-Allow-Origin: * |
Access-Control-Allow-Origin表示允许跨域访问的host,后端将其设置成了’*’,代表允许所有网站的跨域请求,当这种情况的时候,即便Access-Control-Allow-Credentials为true,那也会被浏览器认定为是不安全的,就不能将cookie发送到服务端。
- 数据包中必须包含个人信息才能响应的,也不存在漏洞,如数据包中必须包含电话号码
- 有token进行验证
- 有签名
- 传入的参数中必须包含用户的一些用户名之类(这个只能说限制太多,首先你得获取到别人的用户名之类,其次你还要一个搞成一个专属的链接给他人点击,就这两个条件太苛刻,危害不大,但是如果你想交也可以蛮交)
简单请求
1、请求方式为GET,POST,HEAD这三种之一
2、HTTP头不超出以下这几个字段
1 | Accept |
当浏览器发现服务器的请求为简单请求时,会在头信息里加入Origin字段。Origin字段代表此次请求来自哪个域,服务器就可以检验是否来自该域。如果匹配,服务器就会在响应包中增添三个字段:
1 | Access-Control-Allow-Origin |
其中 Access-Control-Allow-Origin是必须有的,而剩下两个可有可无。
GET型CORS
有Referer先删除Referer,然后发送看是否能够正常请求
这里在请求包中修改Origin字段,发现响应包的Access-Control-Allow-Origin会随之改变,即存在有CORS配置不当漏洞
利用脚本:
1 | <!DOCTYPE html> |
将上面的内容保存为HTML,在登录该账号的浏览器中访问即可
POST型CORS
有的时候我们会遇到post请求,post请求就得使用以下脚本。
1 | <!DOCTYPE html> |
靶场复现
使用 burp 的 CORS 靶场
Lab1: CORS vulnerability with basic origin reflection
This website has an insecure CORS configuration in that it trusts all origins.
To solve the lab, craft some JavaScript that uses CORS to retrieve the administrator’s API key and upload the code to your exploit server. The lab is solved when you successfully submit the administrator’s API key.
You can log in to your own account using the following credentials: wiener:peter
该网站具有不安全的CORS配置,因为它信任所有来源。 为了解决实验问题,请制作一些使用CORS检索管理员的API密钥并将代码上传到您的漏洞利用服务器的JavaScript。当您成功提交管理员的API密钥时,该实验就解决了。 您可以使用以下凭据登录到自己的帐户:wiener:peter
使用账户登录后,bp抓包看到有敏感信息
添加头部:
1 | Origin: foo.test.com |
我们修改请求包中的Origin字段,返回包中Access-Control-Allow-Origin字段也会对应被改变,根据返回包的字段,说明存在CORS漏洞
使用如下poc:
1 | <!DOCTYPE html> |
将poc保存成html文件,然后使用python开启http服务,访问 http://localhost:端口/xxx.html
当受害者去访问这个html文件时,即可获得用户的敏感信息
在真实场景应用中,可以让响应结果重定向至我们的服务器
现在这个靶场就需要重定向到它指定的服务器
1 | <script> |
拿到 administrator用户的key,提交
Lab2、CORS vulnerability with trusted null origin
这关是添加了Origin字段后,返回包中并没有出现Access-Control-Allow-Origin
但是当我们添加的Origin字段为null时,返回包中才出现了Access-Control-Allow-Origin字段(后端可能将null加入了白名单)
null在这种情况下,攻击者可以使用各种技巧来生成包含Origin 标头中的值的跨源请求,这样就会满足白名单,导致跨域访问。
比如利用iframe沙箱属性进行跨域请求,我们可以构造如下POC
1 | //利用iframe沙箱属性进行跨域请求 |
拿到 administrator用户的key,提交
Lab3: CORS vulnerability with trusted insecure protocols
通过测试发现只有当Origin字段的值为受信任的源时,返回包中才会出现Access-Control-Allow-Origin字段(后端可能设置了Origin的白名单为该站点的子域或者根域)
但是如果白名单中的站点很容易遭受XSS攻击的话,攻击者可以向其投放恶意脚本然后利用CORS的信任关系执行它
这时我们需要找到一个容易遭受XSS攻击的站点(前提是这个站点必须是受信任的源,即该站点的子域或者根域)
在其子域上找到一个存在XSS漏洞的站点,至此,可以构造如下POC,利用XSS漏洞去执行POC
1 | <script> |
防御SORS跨域漏洞
1、正确配置跨域请求
应该在有敏感资源的页面中Access-Control-Allow-Origin头指定正确的可信源,仅允许可信任的站点进行跨域请求。
2、避免将null设置为白名单
应该避免设置Access-Control-Allow-Origin: null,因为有些攻击手段可以利用这一点发动CORS攻击,比如iframe沙箱等等。


















