安全漏洞修复-常见问题及解决方案汇总
1.跨站点请求伪造
在项目进行安全测试时,通过AppScan进行漏洞扫描,出现一下问题:
也就是说请求头中缺失"Referer"或未验证Referer的值。由于是前后端分离的项目,前端使用nginx代理,后端部署在tomcat上。因此在后端需要验证Referer的值,添加如下的过滤器:
package com.ljxx.common.filter;
import com.alibaba.fastjson2.JSON;
import com.zxh.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
@Configuration
@WebFilter(filterName = "CsrfFilter", urlPatterns = "/*")
public class CsrfFilter implements Filter {
/**
* 过滤器配置对象
*/
FilterConfig filterConfig = null;
/**
* 忽略的URL
*/
@Value("${security.csrf.excludes}")
private String excludes;
@Override
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
// 已忽略的URL不拦截
if (isExcludeUrl(request.getServletPath())) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
String referer = request.getHeader("Referer");
String serverName = request.getServerName();
//本地开发的地址直接放行
if (serverName.contains("localhost") || serverName.contains("127.0.0.1")) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
// 判断是否存在外链请求本站
if (null != referer && referer.indexOf(serverName) < 0) {
log.error("系统不支持当前域名的访问=> serverName:{} => referer:{}", serverName, referer);
Result error = Result.error("系统不支持当前域名的访问,referer错误!", 502);
servletResponse.setContentType("application/json; charset=utf-8");
servletResponse.getWriter().write(JSON.toJSONString(error));
servletResponse.getWriter().flush();
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
}
@Override
public void destroy() {
this.filterConfig = null;
}
/**
* 判断是否为忽略的URL
*
* @param url
* URL路径
* @return true-忽略,false-过滤
*/
private boolean isExcludeUrl(String url) {
if (excludes == null || excludes.isEmpty()) {
return false;
}
List<String> urls = Arrays.asList(excludes.split(","));
return urls.stream().map(pattern -> Pattern.compile("^" + pattern)).map(p -> p.matcher(url))
.anyMatch(Matcher::find);
}
}
这里主要验证Referer的值,如果不是合法的值就直接返回错误信息。
除此之外,在nginx进行转发时,还需要将请求头信息带着,否则这里的服务名一直是127.0.0.1,具体配置详见nginx携带请求头。
2."Content-Security-Policy"头缺失
需要配置请求头。具体配置哪种策略需见测试报告的解决建议或参考下面的配置。
3."Content-Security-Policy"头中缺少 "Frame-Anchors"策略或策略不安全
在nginx转发时添加请求头即可
location /api{ ... add_header X-Frame-Options SAMEORIGIN; proxy_pass http://127.0.0.1:8001; }
4."Content-Security-Policy" 头中缺少 "Script-Src" 策略或策略不安全
在nginx转发时添加请求头即可
location /api{ ... add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' "; proxy_pass http://127.0.0.1:8001; }
5."X-Content-Type-Options"头缺失或不安全
在nginx转发时添加请求头即可(在固定值中已进行了配置说明)
location /api{ ... add_header X-Content-Type-Options nosniff; proxy_pass http://127.0.0.1:8001; }
6."X-XSS-Protection"头缺失或不安全
在nginx转发时添加请求头即可(在固定值中已进行了配置说明)
location /api{ ... add_header X-XSS-Protection 1; proxy_pass http://127.0.0.1:8001; }
7.检测到隐藏目录
前端使用nginx代理,访问了不存在的路径出现403,解决办法就是将403转为404即可。首先在nginx的html目录新建404.html,内容自定义:
<html> <head><title>404</title></head> <meta charset="utf-8"> <body bgcolor="white"> <center><h1>404 - Not Found</h1></center> </body> </html>
然后在nginx的server模块中配置将403转到404页面:
server { ... error_page 403 =404 /404.html; }
那么当访问出现403时就显示的404,在一定程度上保护了服务器的安全。
就是这么简单,你学废了吗?感觉有用的话,给笔者点个赞吧 !