XSS 攻击:跨站脚本攻击(Cross Site Scripting),为不和 前端层叠样式表(Cascading Style Sheets)CSS 混淆,故将跨站脚本攻击缩写为 XSS。
XSS(跨站脚本攻击):是指恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。类似于 sql 注入。是目前最普遍的 Web 应用安全漏洞,也是 Web 攻击中最常见的攻击方式之一。
XSS( 跨站脚本攻击)攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是 JavaScript,但实际上也可以包括 Java、 VBScript、ActiveX、 Flash 或者甚至是普通的 HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和 cookie 等各种内容。
XSS攻击示例:
这个类用来过滤请求非法内容,详细代码如下:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
/**
* @ClassName XssRequestWrappers
* @Description TODO
* @Author tongxueqiyue
* @Date 2023/12/18 10:43
* @Version 1.0
*/
public class XssRequestWrappers extends HttpServletRequestWrapper {
private CommonsMultipartResolver multiparResolver = new CommonsMultipartResolver();
public XssRequestWrappers(HttpServletRequest request) {
super(request);
String type = request.getHeader("Content-Type");
if (!StringUtils.isEmpty(type) && type.contains("multipart/form-data")) {
MultipartHttpServletRequest multipartHttpServletRequest = multiparResolver.resolveMultipart(request);
Map<String, String[]> stringMap = multipartHttpServletRequest.getParameterMap();
if (!stringMap.isEmpty()) {
for (String key : stringMap.keySet()) {
String value = multipartHttpServletRequest.getParameter(key);
striptXSS(key);
striptXSS(value);
}
}
super.setRequest(multipartHttpServletRequest);
}
}
@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] = striptXSS(values[i]);
}
return encodedValues;
}
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
return striptXSS(value);
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
return striptXSS(value);
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> map1 = super.getParameterMap();
Map<String, String[]> escapseMap = new HashMap<String, String[]>();
Set<String> keys = map1.keySet();
for (String key : keys) {
String[] valArr = map1.get(key);
if (valArr != null && valArr.length > 0) {
String[] escapseValArr = new String[valArr.length];
for (int i = 0; i < valArr.length; i++) {
String escapseVal = striptXSS(valArr[i]);
escapseValArr[i] = escapseVal;
}
escapseMap.put(key, escapseValArr);
}
}
return escapseMap;
}
//处理非法内容,如果有新的在此处增加即可
public static String striptXSS(String value) {
if (value != null) {
// 替换空字符串,以便清除潜在的恶意脚本
value = value.replaceAll("", "");
// 移除<script>标签及其内容
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 移除带有src属性的标签,支持单引号和双引号包围的属性值
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除</script>标签
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 移除以<script...>开头的标签
scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除eval()函数调用
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除expression()函数调用
scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除以"javascript:"开头的字符串
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 移除以"vbscript:"开头的字符串
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 移除以"onload..."开头的字符串
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除包含任何<和>字符的字符串
scriptPattern = Pattern.compile(".*<.*", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
}
// 返回处理后的字符串
return value;
}
}
在这个过滤器中监听XSSFilter,使用上面写的XssRequestWrappers来处理请求中的非法内容
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* @ClassName XSSFilter
* @Description TODO
* @Author tongxueqiyue
* @Date 2023/12/18 10:45
* @Version 1.0
*/
public class XSSFilter implements Filter {
@Override
public void init(FilterConfig arg0) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(new XssRequestWrappers((HttpServletRequest) request), response);
}
}
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean<XSSFilter> xssFilterRegistrationBean() {
FilterRegistrationBean<XSSFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new XSSFilter());
registrationBean.addUrlPatterns("/*"); // 这里配置需要过滤的URL
registrationBean.setName("xssFilter");
registrationBean.setOrder(1); // 设置过滤器的执行顺序,数字越小越优先
return registrationBean;
}
}
执行这三步应该就可以了,不过启动可能会报错,如果报错添加以下依赖即可:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
到这里XSS存储型漏洞应该就能解决了
参考:
https://blog.csdn.net/qq_25580555/article/details/128237542
https://blog.csdn.net/qq_26244285/article/details/122586506