绿盟科技扫描出JavaWeb项目的一些漏洞

1、检测到目标URL存在宽字节跨站漏洞

2、检测到目标URL存在框架注入漏洞

3、检测到目标URL存在链接注入漏洞

已上三点的解决方案主要是给项目配置过滤器,将URL中的特殊字符过滤掉

CookieHttpOnlyFilter.java文件

package com.zysj.boss.web.filter;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 功能描述:
 * <p>
 *   1.Cookie 设置 httpOnly属性 Cookie 
 *   2.设置 httpOnly属性防止js读取cookie
 * </p>
 *
 * @author steven
 */
public class CookieHttpOnlyFilter implements Filter {


    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		if (!(request instanceof HttpServletRequest)) {
			chain.doFilter(request, response);
			return;
		}
		HttpServletRequest httpReq = (HttpServletRequest) request;
		HttpServletResponse httpResp = (HttpServletResponse) response;
		Cookie[] cookies = httpReq.getCookies();
		if (cookies != null) {
			Cookie cookie = cookies[0];
			if (cookie != null) {
				HttpSession session = httpReq.getSession();
				if (session != null) {
					String sessionId = session.getId();
					// http设置
					// httpResp.addHeader("Set-Cookie", "JSESSIONID=" + sessionId + "; Path=/fis; HttpOnly");
                    // httpResp.addHeader("x-frame-options","SAMEORIGIN");
					// https设置
	                    httpResp.addHeader("Set-Cookie", "JSESSIONID=" + sessionId
	                            + "; Path=/admin;Secure; HttpOnly");
				}
			}
		}
		chain.doFilter(httpReq, httpResp);

	}


    public void destroy() {
	}


    public void init(FilterConfig filterConfig) throws ServletException {
	}

}


XssAndSqlFilter.java文件

package com.zysj.boss.web.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class XssAndSqlFilter implements Filter {

    @Override

    public void destroy() {

// TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        XssAndSqlHttpServletRequestWrapper xssRequest = new XssAndSqlHttpServletRequestWrapper((HttpServletRequest) request);

        chain.doFilter(xssRequest, response);
    }


    @Override
    public void init(FilterConfig arg0) throws ServletException {

// TODO Auto-generated method stub

    }

}

XssAndSqlHttpServletRequestWrapper.java文件

package com.zysj.boss.web.filter;

import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;


public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {

    HttpServletRequest orgRequest = null;

    public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {

        super(request);

        orgRequest = request;

    }


    /**
     * 覆盖getParameter方法,将参数名和参数值都做xss & sql过滤。
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */

    @Override
    public String getParameter(String name) {

        String value = super.getParameter(xssEncode(name));

        if (value != null) {

            value = xssEncode(value);

        }

        return value;

    }


    /**
     * 覆盖getHeader方法,将参数名和参数值都做xss & sql过滤。
     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 getHeaderNames 也可能需要覆盖
     */

    @Override
    public String getHeader(String name) {

        String value = super.getHeader(xssEncode(name));

        if (value != null) {

            value = xssEncode(value);

        }

        return value;

    }


    /**
     * 将容易引起xss & sql漏洞的半角字符直接替换成全角字符
     *
     * @param s
     * @return
     */

    private static String xssEncode(String s) {

        if (s == null || s.isEmpty()) {

            return s;

        } else {

            s = stripXSSAndSql(s);

        }

        StringBuilder sb = new StringBuilder(s.length() + 16);

        for (int i = 0; i < s.length(); i++) {

            char c = s.charAt(i);

            switch (c) {

                case '>':

                    sb.append(">");// 转义大于号

                    break;

                case '<':

                    sb.append("<");// 转义小于号

                    break;

                case '\'':

                    sb.append("'");// 转义单引号

                    break;

                case '\"':

                    sb.append(""");// 转义双引号

                    break;

                case '&':

                    sb.append("&");// 转义&

                    break;

                case '#':

                    sb.append("#");// 转义#

                    break;

                default:

                    sb.append(c);

                    break;

            }

        }

        return sb.toString();

    }

    /**
     * 获取最原始的request
     *
     * @return
     */

    public HttpServletRequest getOrgRequest() {

        return orgRequest;

    }


    /**
     * 获取最原始的request的静态方法
     *
     * @return
     */

    public static HttpServletRequest getOrgRequest(HttpServletRequest req) {

        if (req instanceof XssAndSqlHttpServletRequestWrapper) {

            return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest();

        }

        return req;

    }


    /**
     * 防止xss跨脚本攻击(替换,根据实际情况调整)
     */

    public static String stripXSSAndSql(String value) {

        if (value != null) {

// NOTE: It's highly recommended to use the ESAPI library and

// uncomment the following line to

// avoid encoded attacks.

// value = ESAPI.encoder().canonicalize(value);

// Avoid null characters

/** value = value.replaceAll("", ""); ***/

// Avoid anything between script tags

            Pattern scriptPattern = Pattern

                    .compile(

                            "<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>",

                            Pattern.CASE_INSENSITIVE);

            value = scriptPattern.matcher(value).replaceAll("");

// Avoid anything in a

// src="http://www.yihaomen.com/article/java/..." type of

// e-xpression

            scriptPattern = Pattern.compile(

                    "src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",

                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE

                            | Pattern.DOTALL);

            value = scriptPattern.matcher(value).replaceAll("");

// Remove any lonesome </script> tag

            scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>",

                    Pattern.CASE_INSENSITIVE);

            value = scriptPattern.matcher(value).replaceAll("");

// Remove any lonesome <script ...> tag

            scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",

                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE

                            | Pattern.DOTALL);

            value = scriptPattern.matcher(value).replaceAll("");

// Avoid eval(...) expressions

            scriptPattern = Pattern.compile("eval\\((.*?)\\)",

                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE

                            | Pattern.DOTALL);

            value = scriptPattern.matcher(value).replaceAll("");

// Avoid e-xpression(...) expressions

            scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",

                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE

                            | Pattern.DOTALL);

            value = scriptPattern.matcher(value).replaceAll("");

// Avoid javascript:... expressions

            scriptPattern = Pattern.compile(

                    "javascript[\r\n| | ]*:[\r\n| | ]*",

                    Pattern.CASE_INSENSITIVE);

            value = scriptPattern.matcher(value).replaceAll("");

// Avoid vbscript:... expressions

            scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*",

                    Pattern.CASE_INSENSITIVE);

            value = scriptPattern.matcher(value).replaceAll("");

// Avoid onload= expressions

            scriptPattern = Pattern.compile("onload(.*?)=",

                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE

                            | Pattern.DOTALL);

            value = scriptPattern.matcher(value).replaceAll("");

        }

        return value;

    }
}

在web.xml文件中引用一下

  <filter>
        <filter-name> CookieHttpOnly</filter-name>
        <filter-class>xxx.xxx.filter.CookieHttpOnlyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name> CookieHttpOnly</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

	<!-- 解决xss & sql漏洞 -->

	<filter>
		<filter-name>xssAndSqlFilter</filter-name>
		<filter-class>xxx.xxx.filter.XssAndSqlFilter</filter-class>
	</filter>

	<!-- 解决xss & sql漏洞 -->
	<filter-mapping>
		<filter-name>xssAndSqlFilter</filter-name>
		<url-pattern>*</url-pattern>
	</filter-mapping>

4、Spring Boot Actuator未授权访问

修改spring boot的配置文件  Spring boot 关闭Actuator

在bootstrap.yml中

management:
  server:
    port: -1   # 修改端口,跳过安全漏洞扫描
  endpoints:
    enabled-by-default: false   #关闭监控

5、jQuery 存在 XSS 漏洞 

该问题是由于项目中用的jQuery版本太低的问题,升级Jquery版本为3.6.1,因为升级之后的版本不兼容之前的版本,需要引入JQuery提供的jQuery Migrate v3.4.0

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/jquery-migrate-3.4.0.min.js"></script>

但是其中还会存在一些兼容性问题,在引入之后引入一些改写的方法

/**
 * jQuery.browser | jQuery API Documentation该属性已经在1.9版本中删除,为了兼容老代码
 */
(function () {

	/**
	 * 注意,以下代码,应确保 引用在 jquery 3.6.1, jquery-migrate-3.4.0.min.js,以及 jquery-ui-1.8.10.custom.min.js 等内容之后,否则
	 * 相关的 代码托管 可能会被取代 而 无效。   
	 */

	jQuery.curCSS = function (element, prop, val) {
		return jQuery(element).css(prop, val);
	};

	/**
	 *  James add on 2022.11.24 , 相关代码摘录自 jquery 1.7.2
	 *  此 修复是为了 兼容 以下有关写法,在 append 到 jquery 对象里时,能适应 老版本的渲染逻辑。
	 *     $.append("<div><i class='abc' /> <span>ttt</span></div>");
	 *   上述内容,在 jquery 1.7.2 版本里,会被渲染为:
	 *     <div><i class='abc'></i><span>ttt</span></div>
	 *    
	 *    而在 jquery 3.6.1 里,则会被渲染为:
	 *    <div><i class='abc'><span>ttt</span></i></div>
	 *    
	 *    这是由于 在 旧版 jquery 里,针对 非闭合的标签有过特定处理,而在 jquery 3.6.1  里则移除了这个做法。
	 *    因此直接在 element 的 innterHtml 里面写入 <div><i class='abc' /> <span>ttt</span></div> 这个内容,
	 *    与 3.6.1 里面是一致的。
	 *    
	 *    所以根本上是不规范的 html 写法,只是老版本 jquery 做了容错,而新版本没有容错,因而导致问题。
	 *     
	 */
	var oldAppend = jQuery.fn.append;

	jQuery.fn.append = function () {

		/**
		 * 相关素材来自 jquery 1.7.2 
		 */
		var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;

		if (arguments.length > 0
			&& typeof (arguments[0]) == "string") {
			var elem = arguments[0];
			elem = elem.replace(rxhtmlTag, "<$1></$2>");
			arguments[0] = elem;
		}

		return oldAppend.apply(this, arguments);
	};


	var oldOuterWidth = jQuery.fn.outerWidth;

	jQuery.fn.outerWidth = function () {

		if (arguments.length <= 0) {
			arguments[0] = false;
			arguments.length = 1;
		}

		var result = oldOuterWidth.apply(this, arguments);
		return result === undefined ? 0 : result;
	};

	var oldOuterHeight = jQuery.fn.outerHeight;
	jQuery.fn.outerHeight = function () {

		if (arguments.length <= 0) {
			arguments[0] = false;
			arguments.length = 1;
		}

		var result = oldOuterHeight.apply(this, arguments);
		return result === undefined ? 0 : result;
	};
})();

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值