1 漏洞描述
CORS 不安全配置漏洞指的是在跨域资源共享过程中,由于资源服务器的响应头 Access-Control-Allow-Origin 配置不当导致本应该受限访问的请求网站可以绕过访问控制策略读取资源服务器的数据,造成用户隐私泄露,信息窃取甚至账户劫持的危害。
2 漏洞细节
```
https://xxx.com/external/
```
发现存在该漏洞。
发现 `Access-Control-Allow-Origin` 的值为
```
https://xxx.com.qa5bnet.cn
```
漏洞探测过程的请求流为
第 1 个请求为
```
GET /external/ HTTP/1.1
Host: xxx.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Language: en
Origin: https://xxx.com.qa5bnet.cn
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip
```
第 1 个响应为
```
HTTP/1.1 401
Access-Control-Allow-Methods: GET,POST,OPTIONS,PUT,DELETE
Access-Control-Allow-Origin: https://xxx.com.qa5bnet.cn
Connection: keep-alive
Content-Length: 0
Date: Mon, 13 Nov 2023 02:07:00 GMT
Www-Authenticate: BASIC realm="application"
```
3 漏洞修复
通过 Nginx http_origin 添加 CORS 头,来防止未经授权的跨域请求,只允许来自 http://xxx.com
或 https://xxx.com
的请求;
set $flag 0;
if ($http_origin = ''){
set $flag "${flag}1";
}
if ($http_origin !~* ^(http|https)://xxx\.com$){
set $flag "${flag}1";
}
if ($flag = "01"){
return 403;
}
if ($http_origin ~* ^(http|https)://xxx\.com$) {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods GET,POST;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers DNT,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,Content-Type;
}
以上配置是 Nginx 对 $http_origin
进行了多次检查,然后根据检查结果设置了一个标志 $flag
。最后,根据 $flag
的值,配置是否允许跨域请求,以及是否添加了CORS头。
这个配置的逻辑是:
如果
$http_origin
为空字符串,或者不是以http://xxx.com
或https://xxx.com
开头,将$flag
设置为"01"
。如果
$flag
的值为"01"
,返回 403 状态码,拒绝访问。如果
$http_origin
的值以http://xxx.com
或https://xxx.com
开头,添加CORS头。
配置所在位置如下:
server {
listen 80;
server_name xxx.com;
################## CORE 配置 #################
location / {
set $flag 0;
if ($http_origin = ''){
set $flag "${flag}1";
}
if ($http_origin !~* ^(http|https)://xxx\.com$){
set $flag "${flag}1";
}
if ($flag = "01"){
return 403;
}
if ($http_origin ~* ^(http|https)://xxx\.com$) {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods GET,POST;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers DNT,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,Content-Type;
}
###########################################
#将IP和端口改为DataEase服务器的访问地址和端口
proxy_pass http://192.168.110.251:81/;
server_name_in_redirect off;
# websocket 代理
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}