防止存储性XSS攻击

混江龙づ霸主 提交于 2020-04-06 18:42:46

XSS攻击是跨站脚本攻击,又分存储型和反射型。存储型XSS攻击,就是将攻击脚本存储至数据库,以致所有访问者都会受到攻击。攻击脚本一般会将用户的cookie发送给攻击者,然后攻击者伪造用户登陆。反射型XSS攻击,就是攻击者通过特定的方式(邮件等)发送给用户恶意链接,通过用户点击达到攻击目的。

示例脚本:1'"><img src=x onerror=alert(1)>

如何防止储存型XSS攻击?

JAVA端配置XssFilter:

package com.lyh.util;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang3.StringEscapeUtils;

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    /**
     * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
     * getHeaderNames 也可能需要覆盖
     */
    @Override
    public String getHeader(String name) {
        return StringEscapeUtils.escapeHtml4(super.getHeader(name));
    }

    /**
     * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/>
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String name) {
        return StringEscapeUtils.escapeHtml4(super.getParameter(name));
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values == null || values.length == 0) {
            return values;
        }
        int length = values.length;
        String[] escapseValues = new String[length];
        for (int i = 0; i < length; i++) {
            escapseValues[i] = StringEscapeUtils.escapeHtml4(values[i]);
        }
        return escapseValues;
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> map = super.getParameterMap();
        if (map == null || map.size() == 0) {
            return map;
        }
        Set<Entry<String, String[]>> set = map.entrySet();
        for (Entry<String, String[]> entry : set) {
            String[] values = entry.getValue();
            for (int i = 0; values != null && i < values.length; i++) {
                values[i] = StringEscapeUtils.escapeHtml4(values[i]);
            }
        }

        return map;
    }

    @Override
    public String getQueryString() {
        return StringEscapeUtils.escapeHtml4(super.getQueryString());
    }

}
package com.lyh.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;
import javax.servlet.http.HttpServletResponse;

import com.lyh.util.XssHttpServletRequestWrapper;

/**
 * html浏览器端不缓存,防止XSS跨站脚本攻击、防止跨帧脚本编制攻击(禁止被iFrame引用)
 */
public class XssSecurityFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Expose-Headers", "*");
        chain.doFilter(new XssHttpServletRequestWrapper(request), response);
    }

    @Override
    public void destroy() {

    }
}
package com.lyh.config;

import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.boot.web.servlet.ErrorPageRegistrar;
import org.springframework.boot.web.servlet.ErrorPageRegistry;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import com.lyh.filter.ReSubmitFilter;
import com.lyh.filter.XssSecurityFilter;

/**
 * 2017/3/10.
 */
@Configuration
public class FilterConfiguration {

    @Bean
    public FilterRegistrationBean indexXssSecurityFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean(new XssSecurityFilter());
        registration.addUrlPatterns("/*");
        registration.setName("xssSecurityFilter");
        registration.setOrder(9);
        return registration;
    }
    
    @Bean
    public FilterRegistrationBean reSubmitFilter() {
    	FilterRegistrationBean registration = new FilterRegistrationBean(new ReSubmitFilter());
    	registration.addUrlPatterns("/*");
    	registration.setName("reSubmitFilter");
    	registration.setOrder(10);
    	return registration;
    }


    private CorsConfiguration buildConfig() {

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许请求发送Cookie
        corsConfiguration.setAllowCredentials(Boolean.TRUE);
        // 原始请求的域名
        corsConfiguration.addAllowedOrigin(CorsConfiguration.ALL);
        // 添加请求头字段
        corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
        // 服务器支持的所有跨域请求的方法
        corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
        // 预检请求的有效期,单位为秒。
        corsConfiguration.setMaxAge(3600L);
        return corsConfiguration;
    }

    /**
     * 跨域过滤器
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        CorsFilter corsFilter = new CorsFilter(source);
        return new FilterRegistrationBean(corsFilter);
    }

    @Bean
    public ErrorPageRegistrar errorPageRegistrar(){
    	return new MyErrorPageRegistrar();
    }

    private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

    	@Override
    	public void registerErrorPages(ErrorPageRegistry registry) {
    		registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/404"));
    	}

    }

}

前端将value中的html标签转义

var escapeHTML = function (text) {
        if (typeof text === 'string') {
            return text
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#039;')
                .replace(/`/g, '&#x60;');
        }
        return text;
    };

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!