Preface:

1. Introduction of XSS

Cross Site Script (XSS) is a kind of computer security vulnerability that often appears in Web applications. It is also the most mainstream attack mode in The Web.

XSS refers to that malicious attackers take advantage of the shortcomings of websites that do not escape or filter the data submitted by users, and then add some codes and embed them into web pages, so that other users will execute the corresponding embedded codes when they visit.

1.1 harm of XSS attack 1. Steal user information, such as login account and online bank account

2. Read, tamper with, add and delete enterprise sensitive data by using user identity

3. Stealing important data of commercial value from enterprises

4. Illegal money transfers

5. Force email

6, the website hanging horse

7. Control the victim’s machine to launch attacks on other websites

1.2. Preventing XSS Solution The root cause of XSS is that data submitted by clients is not fully filtered, so the focus is on filtering information submitted by users.

Mark important cookies as HTTP only, so that the document.cookie statement in JS cannot fetch cookies. Only allow the user to enter the data we expect. For example, age Indicates the age of the user. Only digits are allowed, and characters other than digits are filtered out. Html Encode processing for data: When the user submits the data, Html encoding is carried out, and the corresponding symbols are converted into entity names for the next step of processing. Filter or remove special Html tags such as

2. Introduction to SQL injection

SQL injection is one of the common network attack methods. It is mainly used to insert SQL commands into Web forms to submit or enter query strings for domain names or page requests, so as to log in without accounts or even tamper with databases.

2.1 Hazards of SQL injection 1. Database information leakage: users’ privacy information stored in the database is leaked.

2. Web page tampering: tamper with specific web pages by operating the database.

3. The database is maliciously operated: The database server is attacked

4. The server is remotely controlled and a rear door is installed

5. Delete and modify database information

2.2. Ways to prevent SQL injection Typically, SQL injection locations include:

(1) Form submission, mainly POST request, but also GET request;

(2) URL parameter submission, mainly for GET request parameters;

(3) Cookie parameter submission;

(4) Some modifiable values of HTTP request headers, such as Referer and User_Agent;

Solution (1) Verifies user input and filters incoming parameters using regular expressions

(2) Use parameterized statements, do not concatenate SQL, can also use secure stored procedures

(3) Do not use database connections with administrator privileges. Use limited database connections for each application

(4) Check the data store type

(5) Important information must be encrypted

SpringBoot project code example: XssFilter:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
 
@Compent
public class XssFilter implements Filter {
 
    FilterConfig filterConfig = null;
 
    private List<String> urlExclusion = null;
 
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
 
    public void destroy(a) {
        this.filterConfig = null;
    }
 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String servletPath = httpServletRequest.getServletPath();
 
        if(urlExclusion ! =null && urlExclusion.contains(servletPath)) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(newXssHttpServletRequestWrapper((HttpServletRequest) request), response); }}public List<String> getUrlExclusion(a) {
        return urlExclusion;
    }
 
    public void setUrlExclusion(List<String> urlExclusion) {
        this.urlExclusion = urlExclusion; }}Copy the code


XssHttpServletRequestWrapper:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
 
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
 
    public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
 
        super(servletRequest);
 
    }
 
    public String[] getParameterValues(String parameter) {
 
        String[] values = super.getParameterValues(parameter);
 
        if (values == null) {
 
            return null;
 
        }
 
        int count = values.length;
 
        String[] encodedValues = new String[count];
 
        for (int i = 0; i < count; i++) {
 
            encodedValues[i] = cleanXSS(values[i]);
 
        }
 
        return encodedValues;
 
    }
 
    public String getParameter(String parameter) {
 
        String value = super.getParameter(parameter);
 
        if (value == null) {
 
            return null;
 
        }
 
        return cleanXSS(value);
 
    }
 
    public String getHeader(String name) {
 
        String value = super.getHeader(name);
 
        if (value == null)
 
            return null;
 
        return cleanXSS(value);
 
    }
 
    private String cleanXSS(String value) {
 
        //You'll need to remove the spaces from the html entities below
 
        value = value.replaceAll("<"."& lt;").replaceAll(">"."& gt;");
 
        value = value.replaceAll("\\("."& # 40;").replaceAll("\\)"."& # 41;");
 
        value = value.replaceAll("'"."& # 39;");
 
        value = value.replaceAll("eval\\((.*)\\)"."");
 
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']"."\" \ "");
 
        value = value.replaceAll("script"."");
 
        returnvalue; }}Copy the code


This is its configuration, in which the interceptor or filter does Xss and Sql injection on a request to avoid operations:

GetRequest:

/** * get HttpServletRequest wrapped against Xss Sql injection *@return request
     */
    public static HttpServletRequest getRequest(a) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return new WafRequestWrapper(request);
    }
 
​
Copy the code


WafRequestWrapper:

public class WafRequestWrapper extends HttpServletRequestWrapper {
 
	private boolean filterXSS = true;
 
	private boolean filterSQL = true;
 
 
	public WafRequestWrapper(HttpServletRequest request, boolean filterXSS, boolean filterSQL) {
		super(request);
		this.filterXSS = filterXSS;
		this.filterSQL = filterSQL;
	}
 
 
	public WafRequestWrapper(HttpServletRequest request) {
		this(request, true.true);
	}
 
 
	/ * * *@DescriptionArray parameter filtering *@paramParameter * Filter parameter *@return* /
	@Override
	public String[] getParameterValues(String parameter) {
		String[] values = super.getParameterValues(parameter);
		if ( values == null ) {
			return null;
		}
 
		int count = values.length;
		String[] encodedValues = new String[count];
		for ( int i = 0 ; i < count ; i++ ) {
			encodedValues[i] = filterParamString(values[i]);
		}
 
		return encodedValues;
	}
 
	@Override
	@SuppressWarnings({ "rawtypes"."unchecked" })
	public Map getParameterMap(a) {
		Map<String, String[]> primary = super.getParameterMap();
		Map<String, String[]> result = new HashMap<String, String[]>(primary.size());
		for ( Map.Entry<String, String[]> entry : primary.entrySet() ) {
			result.put(entry.getKey(), filterEntryString(entry.getValue()));
		}
		return result;
 
	}
	
	protected String[] filterEntryString(String[] rawValue) {
		for ( int i = 0 ; i < rawValue.length ; i++ ) {
			rawValue[i] = filterParamString(rawValue[i]);
		}
		return rawValue;
	}
 
	/ * * *@DescriptionParameter filtering@paramParameter * Filter parameter *@return* /
	@Override
	public String getParameter(String parameter) {
		return filterParamString(super.getParameter(parameter));
	}
 
 
	/ * * *@DescriptionRequest header filtering *@paramName * Filter content *@return* /
	@Override
	public String getHeader(String name) {
		return filterParamString(super.getHeader(name));
	}
 
 
	/ * * *@DescriptionCookie content filtering *@return* /
	@Override
	public Cookie[] getCookies() {
		Cookie[] existingCookies = super.getCookies();
		if(existingCookies ! =null) {
			for (int i = 0; i < existingCookies.length ; ++i) { Cookie cookie = existingCookies[i]; cookie.setValue(filterParamString(cookie.getValue())); }}return existingCookies;
	}
 
	/ * * *@DescriptionFilter string content *@paramRawValue * Content to be processed *@return* /
	protected String filterParamString(String rawValue) {
		if (null == rawValue) {
			return null;
		}
		String tmpStr = rawValue;
		if (this.filterXSS) {
			tmpStr = stripXSS(rawValue);
		}
		if (this.filterSQL) {
			tmpStr = stripSqlInjection(tmpStr);
		}
		return tmpStr;
	}
	
	/ * * *@DescriptionFilter XSS script content *@paramValue * Content to be processed *@return* /
	public static String stripXSS(String value) {
		String rlt = null;
 
		if (null! = value) {// 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
			rlt = value.replaceAll(""."");
 
			// Avoid anything between script tags
			Pattern scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
 
			// Avoid anything in a src='... ' type of expression
			/*scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); rlt = scriptPattern.matcher(rlt).replaceAll(""); scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); rlt = scriptPattern.matcher(rlt).replaceAll(""); * /
 
			// Remove any lonesome </script> tag
			scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
 
			// Remove any lonesome 
			scriptPattern = Pattern.compile("
       (.*?)>, Pattern.CASE_INSENSITIVE
					| Pattern.MULTILINE | Pattern.DOTALL);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
 
			// Avoid eval(...) expressions
			scriptPattern = Pattern.compile("eval\\((.*?) \ \", Pattern.CASE_INSENSITIVE
					| Pattern.MULTILINE | Pattern.DOTALL);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
 
			// Avoid expression(...) expressions
			scriptPattern = Pattern.compile("expression\\((.*?) \ \", Pattern.CASE_INSENSITIVE
					| Pattern.MULTILINE | Pattern.DOTALL);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
 
			// Avoid javascript:... expressions
			scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
 
			// Avoid vbscript:... expressions
			scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
 
			// Avoid onload= expressions
			scriptPattern = Pattern.compile("onload(.*?) =", Pattern.CASE_INSENSITIVE
					| Pattern.MULTILINE | Pattern.DOTALL);
			rlt = scriptPattern.matcher(rlt).replaceAll("");
		}
		
		return rlt;
	}
 
	/ * * *@DescriptionFilter SQL injection content *@paramValue * Content to be processed *@return* /
	public static String stripSqlInjection(String value) {
		return (null == value) ? null : value.replaceAll("('.+--)|(--)|(%7C)".""); //value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
	}
 
	/ * * *@DescriptionFilter SQL/XSS injection content *@paramValue * Content to be processed *@return* /
	public static String stripSqlXSS(String value) {
		returnstripXSS(stripSqlInjection(value)); }}Copy the code