CORS跨域资源共享漏洞
Posted 诡墨佯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CORS跨域资源共享漏洞相关的知识,希望对你有一定的参考价值。
产生原因
同源策略(SOP)限制了应用程序之间的信息共享,并且仅允许在托管应用程序的域内共享。这有效防止了系统机密信息的泄露。但与此同时,也带来了另外的问题。随着Web应用程序和微服务使用的日益增长,出于实用目的往往需要将信息从一个子域传递到另一个子域,或者在不同域之间进行传递(例如将访问令牌和会话标识符,传递给另一个应用程序)。
为了允许跨域通信,开发人员必须使用不同的技术来绕过SOP并传递敏感信息,以至于现今也成为了一个棘手的安全问题。因此,为了在不影响应用程序安全状态的情况下实现信息共享,在html5中引入了跨源资源共享(CORS)。但问题也随之而来,许多人为了方便干脆直接使用默认的配置,或是由于缺乏对此的了解而导致了错误的配置。
CORS跨域资源共享
CORS(Cross-Origin Resource Sharing)跨源资源共享,是HTML5的一个新特性,其思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服AJAX只能同源使用的限制。
CORS的基本原理是,第三方网站服务器生成访问控制策略,指定用户浏览器放宽 SOP 的限制,实现与指定的目标网站共享数据
CORS跨域漏洞的本质是服务器配置不当,即Access-Control-Allow-Origin取自请求头Origin字段,Access-Control-Allow-Credentials设置为true。导致攻击者可以构造恶意的脚本 , 诱导用户点击获取用户敏感数据
(PS:大部分漏洞的出现都是服务器配置不当。)
这里要注意的是,我们也可以测试下带有Access-Control-Allow-Origin: * 字段的网站是否有CORS漏洞,但是如果是如下组合,则没有漏洞,因为浏览器已经会阻止如下的配置。
1 Access-Control-Allow-Origin: *
2 Access-Control-Allow-Credentials: true
(PS:如果有上面两行,则不存在该漏洞。)
CORS中关键的几个响应头字段如下:
Access-Control-Allow-Origin:指定哪些外域可以访问本域资源;
Access-Control-Allow-Credentials:指定浏览器是否将使用请求发送Cookie。仅当设置为true时,才会发送Cookie;默认是false
Access-Control-Allow-Methods:指定可以使用哪些HTTP请求方法(GET、POST、PUT、DELETE等)来访问资源;
Access-Control-Allow-Headers:指定可以在请求报文中添加的HTTP头字段;
Access-Control-Max-Age:指定超时时间;
手工验证方式
在正常的api请求处,headers加入"origin":"http://xx.xx.xx.xx", 如果接口正常返回了数据且headers里包含
1 access-control-allow-credentials : true
2 access-control-allow-origin : http://xx.xx.xx.xx
就说明这个接口确实存在CORS漏洞
挖掘
使用burpsuite
选择Proxy模块中的Options选项,找到Match and Replace这一栏,勾选Request header 将空替换为Origin:foo.example.org
的Enable框。
在Filter by search term 中输入:Access-Control-Allow-Origin: foo.example.org
HTTP history列表中出现符合条件的请求包,点击Ctrl+R,点击GO,如下图,即该处有CORS漏洞。
组合应是这种:
Access-Control-Allow-Origin: foo.example.org
Access-Control-Allow-Credentials: true
注意!如下组合是没有漏洞的。因为浏览器已经会阻止如下配置。
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
其他方法看
【漏洞利用】跨域资源共享(CORS)漏洞详解 - GorillaLee - 博客园 (cnblogs.com)
cors漏洞危害
攻击者构造恶意的html页面,利用链接诱导受害者进行点击,从而获取到受害者的敏感信息
相比之下,CORS较JSONP更为复杂,JSONP只能用于获取资源(即只读,类似于GET请求),而CORS支持所有类型的HTTP请求,功能完善
修复防范
- 关闭非正式开启的CORS
- 白名单限制:定义“源”的白名单,避免使用正则表达式,不要配置
Access-Control-Allow-Origin
为通配符*
或null
,严格效验来自请求数据包中Origin
的值 - 仅允许使用安全协议,避免中间人攻击
- 彻底的返回
Vary: Origin
右边,突破攻击者利用浏览器缓存进行攻击 - 避免将
Access-Control-Allow-Credentials
标头设置为true
替换值,跨域请求若不存在必要的凭证数据,则根据实际情况将其设置为false
- 限制跨域请求允许的方法,
Access-Control-Allow-Methods
替代地减少所涉及的方法,降低风险 - 限制浏览器缓存期限:建议通过
Access-Control-Allow-Methods
和Access-Control-Allow-Headers
限制,限制浏览器缓存信息的时间。通过配置Access-Control-Max-Age
标头来完成,该头部接收时间数作为输入,该数字是浏览器保存缓存的时间。的值,确保浏览器在短时间内可以更新策略 - 仅在接收到跨域请求时才配置有关于跨域的头部,并确保跨域请求是合法的源,以减少攻击者恶意利用的可能性。
Nginx使用“逻辑与”配置origin限制,修复CORS跨域漏洞
目录
1.漏洞报告
- 漏洞名称: CORS 跨域
- 漏洞等级: 中危
- 漏洞证明: Origin从任何域名都可成功访问,未做任何限制。
- 漏洞危害: 因为同源策略的存在,不同源的客户端脚本不能访问目标站点的资源,如果目标站点并配置不当,没有对请求源的域做严格限制,导致任意源都可以访问时,就能在 CORS 跨域漏洞问题,CORS 漏洞一般用于窃取用户敏感数据,如果用户点击触发了而已页面,就会被盗取数据。
- 解决建议: 修复方法是合理配置 CORS,判断 Origin 是否合法。具体说就是请求头不要配置
Access-Control-Allow-Origin
为*
或null
。
2.漏洞复现
复现方式为在 Header 中指定 Origin 请求头,看是否可以请求成功。
curl -H 'Origin:http://aaa.bbb' http://10.14.32.138:80
发现确实可以正常请求成功,开始修复。
3.Nginx 修复
3.1 添加请求头
location /myProject/api/
add_header 'Access-Control-Allow-Origin' 'http://10.14.32.138:80' always;
add_header 'Access-Control-Allow-Credentials' 'false' always;
include proxy_params;
proxy_pass http://localhost:8081/;
access_log /tmp/httplogs/uat-mobileapi-access.log main;
error_log /tmp/httplogs/uat-mobileapi-error.log;
添加完毕,提交复测,发现即使添加了请求头配置,当origin为其他域名时仍能正常访问。
3.2 配置origin限制
进一步通过添加 origin 限制来修复,其他域名访问时,直接返回 403 状态码。
location /myProject/api/
if ($http_origin !~* "(www.test.com|10.14.32.138)" )
return 403;
add_header 'Access-Control-Allow-Origin' 'http://10.14.32.138:80' always;
add_header 'Access-Control-Allow-Credentials' 'false' always;
include proxy_params;
proxy_pass http://localhost:8081/;
access_log /tmp/httplogs/uat-mobileapi-access.log main;
error_log /tmp/httplogs/uat-mobileapi-error.log;
配置之后,发现虽然跨域请求被限制住了,但是页面上的请求也无法访问了。
排查发现,页面上请求时不会传 Origin 请求头,所以也返回 403 状态码了。
2.3 调整origin限制
需要将 Origin 限制改为 Origin 为空也可以正常访问。
location /myProject/api/
set $allow_cors 0;
# 判断不为空
if ($http_origin)
set $allow_cors 1;
# 判断不在白名单内
if ($http_origin !~* "(www.test.com|10.14.32.138)" )
set $allow_cors "$allow_cors1";
# 判断不为空 且 不在白名单内,返回403
if ($allow_cors = "11")
return 403;
add_header 'Access-Control-Allow-Origin' 'http://10.14.32.138:80' always;
add_header 'Access-Control-Allow-Credentials' 'false' always;
include proxy_params;
proxy_pass http://localhost:8081/;
access_log /tmp/httplogs/uat-mobileapi-access.log main;
error_log /tmp/httplogs/uat-mobileapi-error.log;
配置之后,复测通过,页面也可以正常访问了。
整理完毕,完结撒花~
参考地址:
1.Nginx配置origin限制跨域请求(应对等保),https://blog.csdn.net/qq_20236937/article/details/128640137
2.Nginx:如果头不存在或错误,则拒绝请求,https://www.it1352.com/1679888.html
3.NGINX实现IF语句里的AND,OR多重判断,https://blog.51cto.com/qiangsh/1967549
以上是关于CORS跨域资源共享漏洞的主要内容,如果未能解决你的问题,请参考以下文章