I haven’t updated my blog for a long time. It’s more because of self-discipline. I need to keep studying and write some notes for study. Before at the time of learning, always didn’t pay attention to site safety aspects, in the B stand today accidentally saw the XSS related content, today is a good comb XSS related knowledge, can in the later work to avoid XSS the threat posed by the web site, in fact, a web site can safe operation, need further study safety knowledge.

What is XSS?

An explanation from Baidu.com

Through the use of webpage development left loopholes, through the clever method to inject malicious instruction code to the webpage, the user load and execute the malicious web page program made by the attacker. These malicious web programs are usually JavaScript, but can actually include Java, VBScript, ActiveX, Flash, or even plain HTML. After a successful attack, the attacker may gain various contents including but not limited to higher permissions (such as performing some operations), private web content, sessions and cookies.

I think:

XSS refers to malicious users uploading malicious script codes to access users’ private resources

In the project where the front and back end are separated, no matter JWT or other technologies are used, we prefer to keep the Token of the back end in the front end. If there is XSS attack, there will be a threat, such as: After the user logs in successfully, the malicious program will call localstorage. getItem to obtain the user’s token and send the token to the malicious user through Ajax or other means. Malicious users can use this token to access restricted resources and obtain private information.

The above is a simple XSS attack diagram, because the main purpose is to express the meaning simply, some expressions and ideas may not be perfect, I will supplement later

Second, the harm of XSS attack

For example, when users post or register, enter ** in the text box, this code is not escaped, but directly saved to the database. When the view layer renders the HTML in the future, this code will be printed to the page, and the contents of the

<html>// The script will run directly<script>alert('xss')</script>
</html>
Copy the code

Therefore, the most effective way to avoid XSS attack is to escape the data entered by the user and store it in the database. Wait until the view layer renders the HTML page. Escaped text is not executed as JavaScript, which protects against XSS attacks.

1. Upload malicious codes<script>alert("xss")</script>2. The alert(" XSS ") escaped by the server will not be processed as a script, and all labels will be removed as a simple stringCopy the code

3. Address XSS threats

Here we use the HuTool utility class, which provides a solution to the XSS threat

Htmlutil. filter Filters HTML text to prevent XSS attacks. String HTML ="<alert></alert>";
// Result: ""
String filter = HtmlUtil.filter(html);
Copy the code

hutool.cn/

3.1 Importing Dependencies

<! Hutool --> <dependency> <groupId>cn. Hutool </groupId> <artifactId>hutool-all</artifactId> <version>5.4. 0</version>
</dependency>
Copy the code

3.2 Define the request wrapper class

HttpServletRequest is an interface with many methods to implement, which would be a time-consuming operation and impractical to implement.

So, we choose to inherit HttpServletRequestWrapper * * * *

HttpServletRequestWrapper is to use the decorator pattern, also is equivalent to a filter, if you need to obtain parameters or return values only needs to inherit this class to rewrite a method can be achieved, such as: We need to intercept the request, if the value of the request parameter is equal to Yangzinan, we convert it to mic, we just need to inherit and override the method in it:

 @Override
    public String getParameter(String name) {
        // Get parameters
        String value = super.getParameter(name);
        if(value == "yangzinan"){
            value = "mic";
        }
      	// The servlet returns value as mic
        return value;
    }
Copy the code

Let’s start coding now:

/** * prevent XSS attacks */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

    /** * constructor that passes request to the parent class *@param request
     */
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    /** * get the argument, escape the argument *@param name
     * @return* /
    @Override
    public String getParameter(String name) {
        // Get parameters
        String value = super.getParameter(name);
        if(! StrUtil.hasBlank(value)){// Escape the argument
            value = HtmlUtil.filter(value);
        }
        return value;
    }

    /** * Returns array *@param name
     * @return* /
    @Override
    public String[] getParameterValues(String name) {
        // Get the collection
        String[] values = super.getParameterValues(name);
        // Check whether the set is empty, if not, escape
        if(values ! =null) {// go through the number group
            for(int i = 0; i < values.length; i++){ String value = values[i];if(! StrUtil.hasBlank(value)){/ / escape
                    value = HtmlUtil.filter(value);
                }
                // Put the escaped data back into the arrayvalues[i] = value; }}return values;
    }

    /** * get the data in the request header and escape *@param name
     * @return* /
    @Override
    public String getHeader(String name) {
        String value =  super.getHeader(name);
        if(! StrUtil.hasBlank(value)){ value = HtmlUtil.filter(value); }return value;
    }

    /** * get argument *@return* /
    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> parameterMap = super.getParameterMap();
        Since super.getParameterMap() returns a Map, we need to define the Map implementation class to encapsulate the data
        Map<String,String[]> params = new LinkedHashMap<>();
        // If the parameter is not null
        if(parameterMap ! =null) {// Iterate over the map
            for(String key:parameterMap.keySet()){
                // Get value based on key
                String[] values = parameterMap.get(key);
                // go through the number group
                for(int i = 0; i<values.length; i++){ String value = values[i];if(! StrUtil.hasBlank(value)){/ / escape
                        value = HtmlUtil.filter(value);
                    }
                    // Put the escaped data back into the array
                    values[i] = value;
                }
                // Put the escaped array into linkMapparams.put(key,values); }}return params;
    }

    /** * get input stream *@return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream(a) throws IOException {
        // Get the input stream
        ServletInputStream in = super.getInputStream();
        // Used to store input streams
        StringBuffer body = new StringBuffer();
        InputStreamReader reader = new InputStreamReader(in, Charset.forName("UTF-8"));
        BufferedReader bufferedReader = new BufferedReader(reader);
        // Read the input stream line by line
        String line = bufferedReader.readLine();
        while(line ! =null) {// Append the first row of data to a StringBuffer
            body.append(line);
            // Continue reading the next stream until line is empty
            line = bufferedReader.readLine();
        }
        / / close the flow
        bufferedReader.close();
        reader.close();
        in.close();

        // Convert body to map
        Map<String,Object> map = JSONUtil.parseObj(body.toString());
        // Create an empty map to store the results
        Map<String,Object> resultMap = new HashMap<>(map.size());
        // go through the number group
        for(String key:map.keySet()){
            Object value = map.get(key);
            // If map.get(key) returns a string, escape it. If not, store the resultMap directly
            if(map.get(key) instanceof String){
                resultMap.put(key,HtmlUtil.filter(value.toString()));
            }else{ resultMap.put(key,value); }}// Convert the resultMap to a JSON string
        String resultStr = JSONUtil.toJsonStr(resultMap);
        // Convert the JSON string to bytes
        final ByteArrayInputStream bis = new ByteArrayInputStream(resultStr.getBytes());

        // Implement the interface
        return new ServletInputStream() {
            @Override
            public boolean isFinished(a) {
                return false;
            }

            @Override
            public boolean isReady(a) {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {}@Override
            public int read(a) throws IOException {
                returnbis.read(); }}; }}Copy the code

3.3 Creating a Filter

We need to create a filter and inject our custom request wrapper class into the filter to make it work

/** * XSS filter */
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest) request);
        chain.doFilter(xssHttpServletRequestWrapper,response);
    }

    @Override
    public void destroy(a) {}}Copy the code

Where ** @webfilter (urlPatterns = “/*”)** means to intercept all requests and escape all parameters

3.4 test

To test, we need to add **@ServletComponentScan** annotations

@ServletComponentScan
@SpringBootApplication
public class GoflyWxApiApplication {

   public static void main(String[] args) { SpringApplication.run(GoflyWxApiApplication.class, args); }}Copy the code

Test controller

@Api(" Test interface ")
@RestController
public class TestController {

    @PostMapping("/test")
    public R testController(@Valid @RequestBody TestForm testForm){
        return R.ok().put("message"."hello,"+testForm.getName()); }}Copy the code

That’s all for today. These days, I’m looking at Rabbitmq. Good night 😴