What is XSS? How to defend? Teach you how to configure XSS defense in Springboot, and in-depth code analysis!


One, a brief look at XSS

Come, Baidu first copy a paragraph.
HTML is a hypertext markup language that distinguishes text and markup by treating some characters specially. For example, the less than symbol (<) is regarded as the beginning of HTML tags, and the characters between are the title of the page, etc. When the content inserted in the dynamic page contains these special characters (such as <), the user’s browser will mistake it for inserting HTML tags. When these HTML tags introduce a JavaScript script, these scripts will be displayed on the user. Execute in the browser. Therefore, when these special characters cannot be checked by the dynamic page or there is an error in the check, an XSS vulnerability will occur. Let
's use an easy-to-understand example to introduce it.
Before using the defense, suppose there is a user management and user registration function. If the user is registered in the front desk, the user name is included, then the box will always pop up when the user management renders this user information. This is a simple XSS attack.

2. How to defend

Traditional XSS defense uses feature matching methods for attack identification, mainly for searching for the keyword "javascript", but this identification is not flexible enough. Whenever there is "javascript" in the submitted information, it will be rigid. Was judged to be an XSS attack.

Defense based on code modification. Web page developers often have some mistakes and vulnerabilities when writing programs. XSS attacks use mistakes and vulnerabilities. Therefore, an ideal method is to reduce vulnerabilities and avoid being attacked by optimizing Web application development: 1) Users For the information submitted to the server, the URL and the attached HTTP headers, POST data, etc. should be queried, and the content that is not in the specified format and length should be filtered. 2) Realize session tokens, CAPTCHA system or HTTP reference header checking to prevent functions from being executed by third-party websites. 3) Confirm that the received content is properly standardized, only contains the smallest and safe tag (no javascript), remove any references to remote content (especially style sheets and javascript), and use HTTP only cookies. .

Client-side layered defense strategy. The layered defense strategy for client-side cross-site scripting attacks is a security model based on independent allocation of threads and layered defense strategies. It is built on the client (browser). This is the biggest difference between it and other models. The reason why client security is so important is that the client is receiving server information and selectively executing related content. This makes it easy to defend against XSS attacks. The model is mainly composed of three parts: 1) A "web page thread analysis module" that allocates independent threads to each web page and analyzes resource consumption; 2) contains four layered defense strategies Rule user input analysis module; 3) XSS information database that saves information about XSS malicious websites on the Internet

If you are in a bad mood, you don’t need to look at the above.
If you are in a good mood, there is actually no need to look at the above because they are all from Baidu.


Google now provides a set of escaping standards. Any greater than sign and less than sign will be converted to other representations for you.
For example: There is a full set here, and I know you all like to watch the full
Insert picture description here
set. The principle is to use this set of standards. The escaped string is stored in the database, and then presented through this rule when the foreground is parsed.
How to transfer, where to transfer? The approach is quite interesting, first put the code out, after all, some people are eager to use it. After the code is released, I will explain it again. I believe that no one does not understand. If they don’t understand, they will sit on my bed and I will explain to you.

SpringBoot configuration XSS defense

First of all, Maven imports the required dependencies. If there are already imported, there is no need to repeat the import. The latest version can be found on the maven official website.

<!--xss防御-->
<dependency>
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.10.2</version>
</dependency>
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.5</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.73</version>
</dependency>

The next thing to do is to write a filter to intercept processing

Write an XssFilter to filter all requests

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
 * XSS过滤器
 * @author Jozz
 */
@WebFilter(filterName="xssFilter",urlPatterns="/*")
public class XssFilter implements Filter {
    
    
    @Override
    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
    
    
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String path = request.getServletPath();
        //由于我的@WebFilter注解配置的是urlPatterns="/*"(过滤所有请求),所以这里对不需要过滤的静态资源url,作忽略处理(大家可以依照具体需求配置)
        String[] exclusionsUrls = {
    
    ".js",".gif",".jpg",".png",".css",".ico"};
        for (String str : exclusionsUrls) {
    
    
            if (path.contains(str)) {
    
    
                filterChain.doFilter(servletRequest,servletResponse);
                return;
            }
        }
        filterChain.doFilter(new XssHttpServletRequestWrapper(request),servletResponse);
    }
    @Override
    public void destroy() {
    
    
    }
};

Then come to a ServletRequest packaging class, this class may appear inexplicable, wait for an explanation.

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringEscapeUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
/**
 * ServletRequest包装类,对request做XSS过滤处理
 * @author Jozz
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    
    
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
    
    
        super(request);
    }

    @Override
    public String getHeader(String name) {
    
    
        return StringEscapeUtils.escapeHtml4(super.getHeader(name));
    }
    @Override
    public String getQueryString() {
    
    
        return StringEscapeUtils.escapeHtml4(super.getQueryString());
    }
    @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) {
    
    
            int length = values.length;
            String[] escapseValues = new String[length];
            for(int i = 0; i < length; i++){
    
    
                escapseValues[i] = StringEscapeUtils.escapeHtml4(values[i]);
            }
            return escapseValues;
        }
        return values;
    }
    @Override
    public ServletInputStream getInputStream() throws IOException {
    
    
        String str=getRequestBody(super.getInputStream());
        Map<String,Object> map= JSON.parseObject(str,Map.class);
        Map<String,Object> resultMap=new HashMap<>(map.size());
        for(String key:map.keySet()){
    
    
            Object val=map.get(key);
            if(map.get(key) instanceof String){
    
    
                resultMap.put(key,StringEscapeUtils.escapeHtml4(val.toString()));
            }else{
    
    
                resultMap.put(key,val);
            }
        }
        str=JSON.toJSONString(resultMap);
        final ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes());
        return new ServletInputStream() {
    
    
            @Override
            public int read() throws IOException {
    
    
                return bais.read();
            }
            @Override
            public boolean isFinished() {
    
    
                return false;
            }
            @Override
            public boolean isReady() {
    
    
                return false;
            }
            @Override
            public void setReadListener(ReadListener listener) {
    
    
            }
        };
    }
    private String getRequestBody(InputStream stream) {
    
    
        String line = "";
        StringBuilder body = new StringBuilder();
        int counter = 0;
        // 读取POST提交的数据内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream, Charset.forName("UTF-8")));
        try {
    
    
            while ((line = reader.readLine()) != null) {
    
    
                body.append(line);
                counter++;
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return body.toString();
    }
}

Finally, the @ServletComponentScan annotation is added to the startup class for scanning filters.

@SpringBootApplication
@MapperScan("com.kid.mapper")
//@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
@ServletComponentScan//扫描过滤器
@EnableCaching
public class Boot {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Boot.class, args);
    }
}

So let me start it now and show the effect
Insert picture description here
. You can see that I entered some illegal characters in the account. I printed the information I got in the background.
Insert picture description here
So in fact, what I received was not like this, it was just being transferred. That's it.

Code analysis

I believe that everyone knows that this incident was successfully defended after being processed through a filter. So what exactly did the filter do? We can see that the filter seems to be shed without doing anything, except that the URL requested by some pictures and other files is allowed.
But let’s take a closer look at the flow, the incoming request object
filterChain.doFilter(new XssHttpServletRequestWrapper(request), servletResponse);
here the request object is wrapped into another object, and a piece of clothing is worn.
In fact, this design pattern is called the decorator pattern, and I also specifically talked about this pattern in the chapter on simple connection pools. You can also find out if you are interested.
Simple connection pool and decorator mode

We can see in the FilterChain interface that the var1 parameter needs to be passed in an object of type ServletRequest, so the object here can be any object that implements the ServletRequest interface.

public interface FilterChain {
    
    
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}

When we look at the source code, we can also see that HttpServletRequest is an interface and inherits the ServletRequest interface

public interface HttpServletRequest extends HttpServletRequest 

Therefore, this place only needs to implement the class that implements the HttpServletRequest interface or the class that implements the HttpServletRequest interface.
Because the request object we get in the filter is of type HttpServletRequest, we want to wrap this in, then we must write a class that implements the HttpServletRequest interface to wrap this request in.

But from the above code, we inherited the HttpServletRequestWrapper object. In fact, this HttpServletRequestWrapper object implements the HttpServletRequest interface and all interfaces, and each method is copied intact.

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper 

The above part is actually known or not, but I think as a programmer, it is necessary to understand these

Then we know that the HttpServletRequest object is only replaced in the filter. Obviously, we want to implement XSS defense. We only need to obtain the string in these methods of getting the string, such as getParameter, to transfer the originally obtained string to the tool class to convert Return to the caller again.

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

The following is a picture I simply drew, hahahahahaha or hahahahahahahahahahahahahahahahahahahaha, let's see. See you in the next chapter!
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_39150049/article/details/109379025