1. The harm of XSS attacks
XSS
attacks usually refer to exploiting vulnerabilities left during web development and injecting malicious instruction code into the network through clever methods.
page, allowing users to load and execute web programs maliciously created by attackers. These malicious web programs are usually
JavaScript
, but in reality
It can actually include
Java
,
VBScript
,
ActiveX
,
Flash
or even plain
HTML
. After the attack is successful, the attack
The user may obtain various permissions including but not limited to higher permissions (such as performing some operations), private web content, sessions and
cookies,
etc.
content.
For example, when a user posts or registers, he or she enters
<script>alert('xss')</script>
in the text box . This code
If it is not escaped, it will be saved directly to the database. When the view layer renders
HTML in the future
, output this code to
page, then the content of the
<script>
tag will be executed.
Normally, we log into a website. If the website uses
HttpSession
to save login credentials, then
SessionId
will
be saved on the browser in the form of
a cookie .
If a hacker posts on this page, fill in the
The JavaScript
code is used to obtain
the cookie
content and send
the cookie content
to the hacker's own email
via
Ajax .
brain. So as long as someone browses the hacker's post on this website, the view layer will render
the HTML
page and the injection will be performed.
XSS script,
so
your
cookie
information is leaked.
Hackers create cookies
on their computers
and can impersonate
Recharge logged in users.
Even though many websites use
JWT
, the login credentials (
Token
token
) are stored in the browser. So using
XSS
script can
By easily
extracting the Token from
Storage
, hackers can still easily impersonate logged-in users.
Therefore , the most effective way to avoid
XSS attacks is to escape the data entered by the user and then store it in the database.
wait until
When the view layer renders
the HTML
page. Escaped text will not be executed as
JavaScript
, which can resist
XSS
attack.
2. Import dependent libraries
Because the Hutool tool kit comes with XSS escape tool classes, we need to import Hutool and then use the Servlet specification
Provided request wrapper class that defines data escaping functionality.
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.0</version>
</dependency>
3. Define the request packaging class
The HttpServletRequest we usually encounter when writing
Web projects
is actually an interface. If we want to redefine please
When looking for a class, extending this interface is the last thing you should do. Because
there are too many abstract methods in the
HttpServletRequest interface, we will
It's too time consuming to implement. So we should choose a simpler way to customize the request class. That is inheritance
HttpServletRequestWrapper
parent class.
JavaEE
is just a standard, and the specific implementation is completed by various application server manufacturers. For example,
Tomcat
is implementing
When the Servlet was standardized, the implementation class of
the HttpServletRequest interface
was customized
. At the same time, the JavaEE specification also defines
HttpServletRequestWrapper , this class is a wrapper
class
of the request class, using the decorator pattern. I have to say here
The design patterns used are really great. No matter how each application server manufacturer implements the
HttpServletRequest
interface,
If the user wants to customize the request, he only needs to inherit
HttpServletRequestWrapper
and override a certain method accordingly, and then
Pass the request into the request wrapper class, and the decorator pattern will replace a corresponding method in the request object. User code and server
The manufacturer's code is completely decoupled. We don't need to care about how
the HttpServletRequest
interface is implemented. With the help of the packaging class, we
We are free to modify the method in the request. Students, with such an elegant code design, you should really study the design model seriously when you have time.
Mode.
package com.example.emos.wx.config.xss;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.json.JSONUtil;
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.LinkedHashMap;
import java.util.Map;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value= super.getParameter(name);
if(!StrUtil.hasEmpty(value)){
value=HtmlUtil.filter(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] values= super.getParameterValues(name);
if(values!=null){
for (int i=0;i<values.length;i++){
String value=values[i];
if(!StrUtil.hasEmpty(value)){
value=HtmlUtil.filter(value);
}
values[i]=value;
}
}
return values;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parameters = super.getParameterMap();
LinkedHashMap<String, String[]> map=new LinkedHashMap();
if(parameters!=null){
for (String key:parameters.keySet()){
String[] values=parameters.get(key);
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (!StrUtil.hasEmpty(value)) {
value = HtmlUtil.filter(value);
}
values[i] = value;
}
map.put(key,values);
}
}
return map;
}
@Override
public String getHeader(String name) {
String value= super.getHeader(name);
if (!StrUtil.hasEmpty(value)) {
value = HtmlUtil.filter(value);
}
return value;
}
@Override
public ServletInputStream getInputStream() throws IOException {
InputStream in= super.getInputStream();
InputStreamReader reader=new InputStreamReader(in, Charset.forName("UTF-8"));
BufferedReader buffer=new BufferedReader(reader);
StringBuffer body=new StringBuffer();
String line=buffer.readLine();
while(line!=null){
body.append(line);
line=buffer.readLine();
}
buffer.close();
reader.close();
in.close();
Map<String,Object> map=JSONUtil.parseObj(body.toString());
Map<String,Object> result=new LinkedHashMap<>();
for(String key:map.keySet()){
Object val=map.get(key);
if(val instanceof String){
if(!StrUtil.hasEmpty(val.toString())){
result.put(key,HtmlUtil.filter(val.toString()));
}
}
else {
result.put(key,val);
}
}
String json=JSONUtil.toJsonStr(result);
ByteArrayInputStream bain=new ByteArrayInputStream(json.getBytes());
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bain.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
4. Create a filter and pass all request objects into the packaging class
In order to make the wrapper class just defined take effect, we also need to create it in com.example.emos.wx.config.xss
XssFilter
filter. The filter intercepts all requests and then passes the requests to the wrapper class so that the wrapper class can cover all requests.
The parameter method of the request, the user obtains the data from the request, all of which are escaped.
package com.example.emos.wx.config.xss;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;
XssHttpServletRequestWrapper wrapper=new XssHttpServletRequestWrapper(request);
filterChain.doFilter(wrapper,servletResponse);
}
@Override
public void destroy() {
}
}
5. Add annotations to the main class
Add the @ServletComponentScan annotation to the SpringBoot main class .