前端项目被扫描出了一个CORS漏洞,记录一下漏洞的复现和修复。

首先要明确,这个问题出在哪里。

我负责的系统是一个前后端分离的应用,前端部署使用Nginx做反向代理。对于前端应用来说client是浏览器,浏览器发起的请求都是通过nginx配置转发到不同后端的服务器。

举个例子,某个用户用浏览器浏览页面,发起了4个请求:
front.domain/api/auth/login -> auth服务
front.domain/api/auth/user -> auth服务
front.domain/api/fund/detail -> fund服务
front.domain/api/gold/overview -> gold服务

上面4个请求,对应了3个后端服务。

这次被扫描出来的漏洞报告中,仅有front.domain/api/fund/detail 这个URL。
但是我们心里要明白,问题出在fund这个服务。
(即所有的front.domain/api/fund/xxx 都存在CORS的风险)

1.漏洞复现
用postman或者其他类似的开发工具向被检查出的接口所在服务发送请求。
我们还用front.domain/api/fund/detail 这个接口说明
(当然也可以用front.domain/api/fund/overview, front.domain/api/fund/xxx, ...
只要这些接口地址存在)

1.1使用postman不修改参数,向front.domain/api/fund/detail接口发送请求
查看返回值,在postman中把response header, response body分别截图(截图1)。

1.2 继续使用postman,在request header中增加一个参数 "Origin", Origin的值随意写,我们就用 www.test.com来举例。 再次front.domain/api/fund/detail接口向发送请求,查看response header,response body再截个图(截图2)。

1.3 对比两次的截图,发现在漏洞存在的情况下截图2中的response body与截图1中的response body 返回值相同(即请求正常返回了)。

而对比两张截图,截图2中的header中会多了2个字段:
"Access-Control-Allow-Origin" 和 "Access-Control-Expose-Headers"

keyvalue
Access-Control-Allow-Origin*
Access-Control-Expose-HeadersAuthorization

在加上了Origin的情况下,请求能够正常响应并返回结果,就已经证明存在了CORS漏洞。

2.漏洞修复
现在要明确,去哪里修复这个漏洞。
答案是要修改Nginx配置,因为用户不直接于后端服务器通信,用户的请求是通过nginx转发到后端的。

2.1修改nginx配置
找到nginx.conf 或者 yaml文件

定位到location /api/auth

location /api/auth {
proxy_pass http://backend.domain.com
}

修改为

location /api/auth {
set $allow_cors 0;
if ($http_origin) {
set $allow_cors 1;
}
if ($http_origin !~* "(www.white-list1.com|www.white-list2.com)" ) {
set $allow_cors "${allow_cors}1";
}
if ($allow_cors = "11") {
return 403;
}

add_header 'Access-Control-Allow-Origin' 'http://www.white-list.com' always;
add_header 'Access-Control-Allow-Credentials' 'false'  always;

proxy_pass http://backend.domain.com
}

其中 www.white-list.com, www.white-list1.com, www.white-list2.com 是可选的。(自定义CORS白名单网站)

对变更的配置写一点解释:

set $allow_cors 0; - 这里定义了一个变量$allow_cors,初始值为0。

if ($http_origin) - 这个条件语句检查请求头中是否包含Origin字段,如果存在,则将$allow_cors设置为1。

if ($http_origin !~* "(www.white-list1.com|www.white-list2.com)" ) - 这个条件语句检查Origin字段的值是否在白名单内,如果不在白名单内,则将$allow_cors的值加1。

if ($allow_cors = "11") - 这个条件语句检查是否同时满足了前两个条件,如果不为空且不在白名单内,则返回403错误。

add_header 'Access-Control-Allow-Origin' 'http://10.14.32.138:80' always; - 如果请求通过了所有的条件检查,这里设置了Access-Control-Allow-Origin响应头,允许特定来源http://www.white-list.com访问资源。

add_header 'Access-Control-Allow-Credentials' 'false' always; - 设置了Access-Control-Allow-Credentials响应头,表示不允许发送认证信息。

结束。

同步更新到自己的语雀
https://www.yuque.com/dirackeeko/blog/wx529mmxq8xyi8ur


DiracKeeko
128 声望2 粉丝