Commit 6bef9021 authored by zengtianlai3's avatar zengtianlai3

Merge branch 'm33' into 'master'

解决xss存储攻击

See merge request !41
parents 69473473 035c16e6
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version> <version>2.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>com.sixiang.iot</groupId> <groupId>com.sixiang.iot</groupId>
...@@ -29,6 +29,19 @@ ...@@ -29,6 +29,19 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!--xss-->
<dependency>
<groupId>org.owasp.esapi</groupId>
<artifactId>esapi</artifactId>
<version>2.2.0.0</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
...@@ -68,7 +81,7 @@ ...@@ -68,7 +81,7 @@
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.28</version> <version>2.0.1</version>
</dependency> </dependency>
<dependency> <dependency>
......
...@@ -24,5 +24,4 @@ public class LicenseApplication implements WebMvcConfigurer { ...@@ -24,5 +24,4 @@ public class LicenseApplication implements WebMvcConfigurer {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(LicenseApplication.class, args); SpringApplication.run(LicenseApplication.class, args);
} }
} }
package iot.sixiang.license.config; package iot.sixiang.license.config;
import iot.sixiang.license.jwt.AuthenticationInterceptor; import iot.sixiang.license.jwt.AuthenticationInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.config.annotation.*;
@Configuration @Configuration
@EnableWebMvc @EnableWebMvc
@Slf4j
public class CorsConfig implements WebMvcConfigurer { public class CorsConfig implements WebMvcConfigurer {
@Autowired @Autowired
AuthenticationInterceptor authenticationInterceptor; AuthenticationInterceptor authenticationInterceptor;
@Override @Override
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") registry.addMapping("/**")
.allowedOriginPatterns("*") .allowedOrigins("*")
.allowedMethods("*") .allowedMethods("*")
.allowCredentials(true) .allowCredentials(true)
.maxAge(3600) .maxAge(3600)
...@@ -24,7 +26,7 @@ public class CorsConfig implements WebMvcConfigurer { ...@@ -24,7 +26,7 @@ public class CorsConfig implements WebMvcConfigurer {
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
System.out.println("重写了addResourceHandlers方法"); log.info("重写了addResourceHandlers方法");
} }
@Override @Override
......
package iot.sixiang.license.jwt; package iot.sixiang.license.jwt;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.DecodedJWT;
import iot.sixiang.license.model.ResResult;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.servlet.*; import javax.servlet.*;
...@@ -25,7 +23,8 @@ public class JwtFilter implements Filter { ...@@ -25,7 +23,8 @@ public class JwtFilter implements Filter {
private static final String url8 = "/webjars/"; private static final String url8 = "/webjars/";
@Override @Override
public void init(FilterConfig filterConfig) throws ServletException { public void init(FilterConfig filterConfig) {
log.info("-------------JwtFilter-init---------------");
} }
@Override @Override
...@@ -85,7 +84,7 @@ public class JwtFilter implements Filter { ...@@ -85,7 +84,7 @@ public class JwtFilter implements Filter {
@Override @Override
public void destroy() { public void destroy() {
log.info("-------------JwtFilter-destroy---------------");
} }
} }
...@@ -12,7 +12,7 @@ import java.text.SimpleDateFormat; ...@@ -12,7 +12,7 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
@Slf4j @Slf4j
public class CommonUtil { public class CommonUtil {
/** /**
* 随机生成指定长度的字符串 * 随机生成指定长度的字符串
......
package iot.sixiang.license.xss;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
/**
* @Author m33
* @Date 2022/6/29 13:59
* @Description
*/
@Configuration
public class XSSFilterConfig {
@Bean
@DependsOn("xssFilter")
public FilterRegistrationBean filterRegistrationBean() {
System.out.println("===================filterRegistrationBean");
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.addInitParameter("paramName", "paramValue");
registration.setName("xssFilter");
return registration;
}
}
package iot.sixiang.license.xss;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @Author m33
* @Date 2022/6/29 11:11
* @Description
*/
@WebFilter(filterName = "xssFilter", urlPatterns = "/iot_license/*", asyncSupported = true)
@Component
public class XssFilter implements Filter {
/**
* 描述 : 日志
*/
private static final Logger LOGGER = LoggerFactory.getLogger(XssFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("==============> 进入init XssFilter");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
LOGGER.info("========>进入XSS过滤器");
chain.doFilter(xssRequest, response);
LOGGER.info("=========>过滤器XSS执行完");
}
@Override
public void destroy() {
LOGGER.info("==============> destroy XssFilter");
}
}
package iot.sixiang.license.xss;
import org.owasp.esapi.ESAPI;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.regex.Pattern;
import static java.util.regex.Pattern.*;
/**
* @Author m33
* @Date 2022/7/4 11:24
* @Description
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
}
@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] = cleanXSS(values[i]);
}
return encodedValues;
}
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return cleanXSS(value);
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if (value == null) {
return null;
}
return 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", "");
//
// return value;
//
// }
private String cleanXSS(String value) {
if (value != null) {
// 推荐使用ESAPI库来避免脚本攻击
value = ESAPI.encoder().canonicalize(value);
// 避免空字符串
value = value.replaceAll("", "");
// 避免script 标签
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
//避免src形式的表达式
//scriptPattern = compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", CASE_INSENSITIVE | MULTILINE | DOTALL);
//value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 删除单个的 </script> 标签
scriptPattern = Pattern.compile("</script>", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 删除单个的<script ...> 标签
scriptPattern = Pattern.compile("<script(.*?)>", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 eval(...) 形式表达式
scriptPattern = Pattern.compile("eval\\((.*?)\\)", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 e­xpression(...) 表达式
scriptPattern = Pattern.compile("expression\\((.*?)\\)", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 javascript: 表达式
scriptPattern = Pattern.compile("javascript:", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 vbscript: 表达式
scriptPattern = Pattern.compile("vbscript:", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 onload= 表达式
scriptPattern = Pattern.compile("onload(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 onXX= 表达式
scriptPattern = Pattern.compile("on.*(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
}
return value;
}
}
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<!--
Slashdot allowed tags taken from "Reply" page:
<b> <i> <p> <br> <a> <ol> <ul> <li> <dl> <dt> <dd> <em> <strong> <tt> <blockquote> <div> <ecode> <quote>
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="500000"/>
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
<!--
From W3C:
This attribute assigns a class name or set of class names to an
element. Any number of elements may be assigned the same class
name or names. Multiple class names must be separated by white
space characters.
-->
<regexp name="htmlTitle" value="[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&amp;]*"/>
<regexp name="onsiteURL" value="^(?!//)(?![\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*(&amp;colon))[\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*"/>
<regexp name="offsiteURL" value="(\s)*((ht|f)tp(s?)://|mailto:)[\p{L}\p{N}]+[\p{L}\p{N}\p{Zs}\.\#@\$%\+&amp;;:\-_~,\?=/!\(\)]*(\s)*"/>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
<attribute name="lang" description="The 'lang' attribute tells the browser what language the element's attribute values and content are written in">
<regexp-list>
<regexp value="[a-zA-Z]{2,20}"/>
</regexp-list>
</attribute>
<attribute name="title" description="The 'title' attribute provides text that shows up in a 'tooltip' when a user hovers their mouse over the element">
<regexp-list>
<regexp name="htmlTitle"/>
</regexp-list>
</attribute>
<attribute name="href" onInvalid="filterTag">
<regexp-list>
<regexp name="onsiteURL"/>
<regexp name="offsiteURL"/>
</regexp-list>
</attribute>
<attribute name="align" description="The 'align' attribute of an HTML element is a direction word, like 'left', 'right' or 'center'">
<literal-list>
<literal value="center"/>
<literal value="left"/>
<literal value="right"/>
<literal value="justify"/>
<literal value="char"/>
</literal-list>
</attribute>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while?
-->
<global-tag-attributes>
<attribute name="title"/>
<attribute name="lang"/>
</global-tag-attributes>
<tag-rules>
<!-- Tags related to JavaScript -->
<tag name="script" action="remove"/>
<tag name="noscript" action="remove"/>
<!-- Frame & related tags -->
<tag name="iframe" action="remove"/>
<tag name="frameset" action="remove"/>
<tag name="frame" action="remove"/>
<tag name="noframes" action="remove"/>
<!-- All reasonable formatting tags -->
<tag name="p" action="validate">
<attribute name="align"/>
</tag>
<tag name="div" action="validate"/>
<tag name="i" action="validate"/>
<tag name="b" action="validate"/>
<tag name="em" action="validate"/>
<tag name="blockquote" action="validate"/>
<tag name="tt" action="validate"/>
<tag name="br" action="truncate"/>
<!-- Custom Slashdot tags, though we're trimming the idea of having a possible mismatching end tag with the endtag="" attribute -->
<tag name="quote" action="validate"/>
<tag name="ecode" action="validate"/>
<!-- Anchor and anchor related tags -->
<tag name="a" action="validate">
<attribute name="href" onInvalid="filterTag"/>
<attribute name="nohref">
<literal-list>
<literal value="nohref"/>
<literal value=""/>
</literal-list>
</attribute>
<attribute name="rel">
<literal-list>
<literal value="nofollow"/>
</literal-list>
</attribute>
</tag>
<!-- List tags -->
<tag name="ul" action="validate"/>
<tag name="ol" action="validate"/>
<tag name="li" action="validate"/>
</tag-rules>
<!-- No CSS on Slashdot posts -->
<css-rules>
</css-rules>
</anti-samy-rules>
\ No newline at end of file
...@@ -6,6 +6,8 @@ spring: ...@@ -6,6 +6,8 @@ spring:
url: jdbc:mysql://rm-wz9w0x7a26q11av687o.mysql.rds.aliyuncs.com:3306/iot_license?serverTimezone=GMT%2B8 url: jdbc:mysql://rm-wz9w0x7a26q11av687o.mysql.rds.aliyuncs.com:3306/iot_license?serverTimezone=GMT%2B8
username: dada username: dada
password: Acc2019123 password: Acc2019123
main:
allow-bean-definition-overriding: true
mybatis-plus: mybatis-plus:
mapper-locations: classpath:/mapper/**.xml mapper-locations: classpath:/mapper/**.xml
type-aliases-package: iot.sixiang.license.entity type-aliases-package: iot.sixiang.license.entity
......
# The ESAPI validator does many security checks on input, such as canonicalization
# and whitelist validation. Note that all of these validation rules are applied *after*
# canonicalization. Double-encoded characters (even with different encodings involved,
# are never allowed.
#
# To use:
#
# First set up a pattern below. You can choose any name you want, prefixed by the word
# "Validation." For example:
# Validation.Email=^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
#
# Then you can validate in your code against the pattern like this:
# ESAPI.validator().isValidInput("User Email", input, "Email", maxLength, allowNull);
# Where maxLength and allowNull are set for you needs, respectively.
#
# But note, when you use boolean variants of validation functions, you lose critical
# canonicalization. It is preferable to use the "get" methods (which throw exceptions) and
# and use the returned user input which is in canonical form. Consider the following:
#
# try {
# someObject.setEmail(ESAPI.validator().getValidInput("User Email", input, "Email", maxLength, allowNull));
#
Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$
Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
Validator.URL=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\'\\/\\\\\\+=&;%\\$#_]*)?$
Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$
Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment