渗透CORS跨域漏洞修复方案

前言

线上系统在等保测评的时候被扫出来了CORS跨域问题,但是根据网上大多数人用的方法之后,发现,还是能被扫出来问题,被这个问题困扰了很久,才找到了问题的解决方案,亲测有效!!!

CORS工作原理:

简单来说,CORS是一种访问机制,英文全称是Cross-Origin Resource Sharing,即我们常说的跨域资源共享,通过在服务器端设置响应头,把发起跨域的原始域名添加到Access-Control-Allow-Origin 即可。

CORS实现跨域访问并不是一蹴而就的,需要借助浏览器的支持,从原理题图我们可以清楚看到,简单的请求(通常指GET/POST/HEAD方式,并没有去增加额外的请求头信息)直接创建了跨域请求的XHR对象,而复杂的请求则要求先发送一个”预检”请求,待服务器批准后才能真正发起跨域访问请求。

根据官方文档 W3C规范-CORS 的描述,目前CORS使用了如下头部信息:

注:请求头信息由浏览器检测到跨域自动添加,无需过多干预,重点放在Response headers,它可以帮助我们在服务器进行跨域授权,例如允许哪些原始域可放行,是否需要携带Cookie信息等。

Request Headers(请求头)
  • Origin
    表示跨域请求的原始域。
  • Access-Control-Request-Method
    表示跨域请求的方式。(如GET/POST)
  • Access-Control-Request-Headers
    表示跨域请求的请求头信息
Response headers(响应头 )
  • Access-Control-Allow-Origin
    表示允许哪些原始域进行跨域访问。(字符数组)
  • Access-Control-Allow-Credentials
    表示是否允许客户端获取用户凭据。(布尔类型)
    使用场景:例如现在从浏览器发起跨域请求,并且要附带Cookie信息给服务器。则必须具备两个条件:1. 浏览器端:发送AJAX请求前需设置通信对象XHR的withCredentials 属性为true。 2.服务器端:设置Access-Control-Allow-Credentials为true。两个条件缺一不可,否则即使服务器同意发送Cookie,浏览器也无法获取。正确姿势如下:
  • Access-Control-Allow-Methods
    表示跨域请求的方式的允许范围。(例如只授权GET/POST)
  • Access-Control-Allow-Headers
    表示跨域请求的头部的允许范围。
  • Access-Control-Expose-Headers
    表示暴露哪些头部信息,并提供给客户端。(因为基于安全考虑,如果没有设置额外的暴露,跨域的通信对象XMLHttpRequest只能获取标准的头部信息)
    • Access-Control-Max-Age
      表示预检请求 [Preflight Request] 的最大缓存时间。
      使用场景:例如现在从浏览器发起跨域请求,并且要附带Cookie信息给服务器。则必须具备两个条件:1. 浏览器端:发送AJAX请求前需设置通信对象XHR的withCredentials 属性为true。 2.服务器端:设置Access-Control-Allow-Credentials为true。两个条件缺一不可,否则即使服务器同意发送Cookie,浏览器也无法获取。正确姿势如下:
  • Access-Control-Allow-Methods
    表示跨域请求的方式的允许范围。(例如只授权GET/POST)
  • Access-Control-Allow-Headers
    表示跨域请求的头部的允许范围。
  • Access-Control-Expose-Headers
    表示暴露哪些头部信息,并提供给客户端。(因为基于安全考虑,如果没有设置额外的暴露,跨域的通信对象XMLHttpRequest只能获取标准的头部信息)
  • Access-Control-Max-Age
    表示预检请求 [Preflight Request] 的最大缓存时间。

1.问题扫描报告

在这里插入图片描述

2.CORS实现跨域访问修复-Nginx方案

删除指定响应头信息
proxy_hide_header Access-Control-Allow-Origin;
添加指定响应头信息
add_header Access-Control-Allow-Origin 'https://www.baidu.com/';
  • 配置location模块的
location / {
    
    
	proxy_pass http://localhsot:8080/web
	add_header Access-Control-Allow-Origin *.xxx.com;
	add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
	add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
}
  • 在http中定义一个通过map指令,定义跨域规则并返回是否合法
http {
    
    
   map $http_origin $allow_cors {
    
    
   		default 1;
   		"~.*baidu.com.*" 1;
   		"~.*192.168.1.10.*" 1;
   		"~.*192.168.1.11.*" 1;
   		"~.*" 0;
   }
   
   server {
    
    
   	   location /school-openwork-order {
    
    
   			 if ($allow_cors = 0){
    
    
   				return 403;
   			 }
   			 proxy_pass http://localhsot:8080/web;
   		}
   	}
}

3.CORS实现跨域访问修复-Java方案

  • 配置CorsFilter(全局跨域)
@Configuration
public class GlobalCorsConfig {
    
    
	@Bean
	public CorsFilter corsFilter() {
    
    
		//1.添加CORS配置信息
		CorsConfiguration config = new CorsConfiguration();
		//放行哪些原始域
		config.addAllowedOrigin("*");
		//是否发送Cookie信息
		config.setAllowCredentials(true);
		//放行哪些原始域(请求方式)
		config.addAllowedMethod("*");
		//放行哪些原始域(头部信息)
		config.addAllowedHeader("*");
		//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
		config.addExposedHeader("*");
		//2.添加映射路径
		UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
		configSource.registerCorsConfiguration("/**", config);
		//3.返回新的CorsFilter.
		return new CorsFilter(configSource);
	}
}
  • 重写WebMvcConfigurer(全局跨域)
@Configuration
public class GlobalCorsConfig {
    
    
	@Bean
	public WebMvcConfigurer corsConfigurer() {
    
    
		return new WebMvcConfigurer() {
    
    
			@Override
			//重写父类提供的跨域请求处理的接口
			public void addCorsMappings(CorsRegistry registry) {
    
    
				//添加映射路径
				registry.addMapping("/**")
				//放行哪些原始域
				.allowedOrigins("*")
				//是否发送Cookie信息
				.allowCredentials(true)
				//放行哪些原始域(请求方式)
				.allowedMethods("GET","POST", "PUT", "DELETE")
				//放行哪些原始域(头部信息)
				.allowedHeaders("*")
				//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
				.exposedHeaders("Header1", "Header2");
			}
		}
	}
}
  • 在方法上(@RequestMapping)使用注解 @CrossOrigin
@RequestMapping("/hello")
@ResponseBody
@CrossOrigin("http://localhost:8080")
public String index( ){
    
    
	return "Hello World";
}
  • 手工设置响应头(局部跨域 )
@RequestMapping("/hello")
@ResponseBody
public String index(HttpServletResponse response){
    
    
	response.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
	return "Hello World";
}
  • Filter过滤器跨域
@Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
    
	HttpServletRequest req = (HttpServletRequest) request;
	HttpServletResponse rep = (HttpServletResponse) response;
	// 设置允许多个域名请求
	String[] allowDomains = {
    
    "http://www.toheart.xin","http://192.168.11.213:8080","http://localhost:8080"};
	Set allowOrigins = new HashSet(Arrays.asList(allowDomains));
	String originHeads = req.getHeader("Origin");
	if(allowOrigins.contains(originHeads)){
    
    
	//设置允许跨域的配置
	// 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
	rep.setHeader("Access-Control-Allow-Origin", originHeads);
}

猜你喜欢

转载自blog.csdn.net/qq_52231508/article/details/143210219