应用安全扫描

3.4.0版本起,已经新增如下安全问题解决方案:

1. 响应头缺失

  • 缺少“Content-Security-Policy”头
  • 缺少“X-Content-Type-Options”头
  • 缺少“X-XSS-Protection”头
  • "Referral Policy" Security 头缺失

解决方法:

nginx.conf在server模块配置:

add_header Content-Security-Policy "default-src 'self'; object-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src * data:; worker-src * blob:; font-src 'self' data:; frame-ancestors 'self';";

add_header X-Content-Type-Options "nosniff";

add_header X-XSS-Protection "1";

add_header 'Referrer-Policy' 'origin';

http修改为https协议

3. 不安全的Http方法

nginx.conf在server模块配置:

if ($request_method !~* GET|POST) {
    return 403;
}

HTTP1.0定义了三种请求方法:GET、POST、HEAD HTTP1.1新增了五种请求方法:OPTIONS、PUT、DELETE、TRACE 、CONNECT 除了GET和POST方法,其他方法都可以视为不安全的方法,根据需求,尽量减少允许的方法

4. 在应用程序中发现不必要的 Http 响应头

响应头中多了:Server: nginx/1.8.0

  • 下载插件(GitHub: https://github.com/openresty/headers-more-nginx-module):

    wget https://github.com/openresty/headers-more-nginx-module/archive/v0.33.tar.gz
    
  • 解压

    tar -zxvf v0.33.tar.gz
    
  • 查看安装参数命令

    ./nginx/sbin/nginx -V
    
  • 重新编译nginx,./configure后面加--add-module=/app/tools/headers-more-nginx-module-0.33

    注意:如果版本不兼容headers-more-nginx-module有部分代码需要修改,根据实际报错代码行修改

  • 最后重启nginx

5. 检测到隐藏目录

对禁止的资源发布“404 - Not Found”响应状态代码,或者将其完全除去

nginx.conf在server模块修改配置(跳转到指定目录下):

## 避免如下配置:
location / {
    proxy_pass http://ip:port/;
}
## 应改为:
location / {
    proxy_pass http://ip:port/xxxxxx/;
}
## 多模块的话应修改为:
location /xxx1 {
    proxy_pass http://ip:port/xxxxxx1/;
}
location /xxx2 {
    proxy_pass http://ip:port/xxxxxx2/;
}

6. 跨站点请求伪造

验证“Referer”头的值,并对每个提交的表单使用 one-time-nonce

解决方案:

  • 1、KEMS 3.0.0+ | KOCA 4.0.0+版本,开启CSRF防御,登录成功后,response头会返回一个XSRF-TOKEN,除过滤的url外,所有请求的request head中需要携带X-Xsrf-Token或请求参数中携带csrf_token 才能正常访问。

    网关的auth.yml新增配置:

    koca:
      security:
        # CSRF防御
        csrf:
          enabled: true
    
  • 2、网关新增Referer拦截器(3.4.0版本已新增)

    pom.xml:

    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>9.0.71</version>
        <scope>compile</scope>
    </dependency>
    

    auth.yml:

    security:
      enabled: true
      csrf:
        excludes:
    

    RefererFilter.java:

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    
    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;
    
    @Component
    @Configuration
    @WebFilter(filterName = "refererFilter", urlPatterns = "/*")
    public class RefererFilter implements Filter {
        public static final Logger logger = LoggerFactory.getLogger(RefererFilter.class);
    
        /**
         * 过滤器配置对象
         */
        FilterConfig filterConfig = null;
    
        /**
         * 是否启用
         */
        @Value("${security.enabled}")
        private boolean enabled;
    
        /**
         * 忽略的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 {
            logger.error("是否启用Referer 跨站点拦截器" + enabled);
            HttpServletRequest request = (HttpServletRequest) servletRequest;
    
            // 不启用或者已忽略的URL不拦截
            if (!enabled || isExcludeUrl(request.getServletPath())) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
    
            String referer = request.getHeader("Referer");
            String serverName = request.getServerName();
    
            // 判断是否存在外链请求本站
            if (null != referer && !referer.contains(serverName)) {
                logger.error("Referer过滤器 => 服务器:{} => 当前域名:{}", serverName, referer);
                servletResponse.setContentType("text/html; charset=utf-8");
                servletResponse.getWriter().write("系统不支持当前域名的访问!");
            } 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);
        }
    }
    

7. 其余因请求参数引发的风险

开启通信加密:

# 前端的public/config.json修改为:
"ENABLE_API_ENCRYPT": true,

# 后端网关bootstrap.yml
koca:
  web:
    encrypt:
      enabled: true  #后台是否开启通信加解密,默认false
Copyright © 2017-2023 深圳金证引擎科技有限公司 all right reserved,powered by Gitbook该文件最后修订时间: 2023-09-15 13:21:40

results matching ""

    No results matching ""