springboot解決XSS存儲型漏洞問題
XSS攻擊
XSS 攻擊
跨站腳本攻擊(Cross Site Scripting),為不和 前端層疊樣式表(Cascading Style Sheets)CSS 混淆,故將跨站腳本攻擊縮寫為 XSS。
XSS(跨站腳本攻擊)
是指惡意攻擊者往 Web 頁面里插入惡意 Script 代碼,當(dāng)用戶瀏覽該頁時,嵌入其中 Web 里面的 Script 代碼會被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的。
類似于 sql 注入。是目前最普遍的 Web 應(yīng)用安全漏洞,也是 Web 攻擊中最常見的攻擊方式之一。
XSS( 跨站腳本攻擊)攻擊通常指的是通過利用網(wǎng)頁開發(fā)時留下的漏洞,通過巧妙的方法注入惡意指令代碼到網(wǎng)頁,使用戶加載并執(zhí)行攻擊者惡意制造的網(wǎng)頁程序。
這些惡意網(wǎng)頁程序通常是 JavaScript,但實際上也可以包括 Java、 VBScript、ActiveX、 Flash 或者甚至是普通的 HTML。
攻擊成功后,攻擊者可能得到包括但不限于更高的權(quán)限(如執(zhí)行一些操作)、私密網(wǎng)頁內(nèi)容、會話和 cookie 等各種內(nèi)容。
XSS攻擊示例


過濾請求非法內(nèi)容XSS類:XssRequestWrappers
這個類用來過濾請求非法內(nèi)容,詳細(xì)代碼如下:
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;
}
//處理非法內(nèi)容,如果有新的在此處增加即可
public static String striptXSS(String value) {
if (value != null) {
// 替換空字符串,以便清除潛在的惡意腳本
value = value.replaceAll("", "");
// 移除<script>標(biāo)簽及其內(nèi)容
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 移除帶有src屬性的標(biāo)簽,支持單引號和雙引號包圍的屬性值
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>標(biāo)簽
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 移除以<script...>開頭的標(biāo)簽
scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除eval()函數(shù)調(diào)用
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除expression()函數(shù)調(diào)用
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;
}
}
定義過濾器監(jiān)聽XSSFilter 重寫Filter
在這個過濾器中監(jiān)聽XSSFilter,使用上面寫的XssRequestWrappers來處理請求中的非法內(nèi)容
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);
}
}
注冊這個XSSFilter為Bean
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); // 設(shè)置過濾器的執(zhí)行順序,數(shù)字越小越優(yōu)先
return registrationBean;
}
}
執(zhí)行這三步應(yīng)該就可以了,不過啟動可能會報錯,如果報錯添加以下依賴即可:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
到這里XSS存儲型漏洞應(yīng)該就能解決了
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot 使用 Swagger 構(gòu)建 RestAPI 接口文檔
這篇文章主要介紹了Spring Boot 使用 Swagger 構(gòu)建 RestAPI 接口文檔,幫助大家更好的理解和使用Spring Boot框架,感興趣的朋友可以了解下2020-10-10
java實現(xiàn)多線程的兩種方式繼承Thread類和實現(xiàn)Runnable接口的方法
下面小編就為大家?guī)硪黄猨ava實現(xiàn)多線程的兩種方式繼承Thread類和實現(xiàn)Runnable接口的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09
從零開始設(shè)計基于SpringBoot的Serverless(本地函數(shù)計算)引擎
最近突然冒出一個想法:能不能用SpringBoot自己實現(xiàn)一個類似AWS Lambda或阿里云函數(shù)計算的執(zhí)行引擎,所以下面我們就來看看如何從零開始設(shè)計一套基于SpringBoot的Serverless執(zhí)行框架吧2025-07-07
Spring超出最大會話數(shù)(Max?sessions?limit?reached:?10000)
在Spring系統(tǒng)中遇到的Maxsessionslimitreached:10000錯誤,該錯誤由于會話數(shù)超過默認(rèn)限制10000而觸發(fā),下面就來介紹一下解決方法,感興趣的可以了解一下2024-12-12
java語言基礎(chǔ)之標(biāo)識符和命名規(guī)則詳解
這篇文章主要給大家介紹了關(guān)于java語言基礎(chǔ)之標(biāo)識符和命名規(guī)則的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
使用EasyPoi實現(xiàn)多Sheet頁導(dǎo)出的示例代碼
在項目開發(fā)中,我們常常會遇到導(dǎo)出多Sheet頁的需求,本文降維打擊介紹一下如何使用EasyPoi實現(xiàn)這一功能,文中的示例代碼簡潔易懂,有需要的可以參考下2025-03-03
Spring中的@RestControllerAdvice注解使用方法解析
這篇文章主要介紹了Spring中的@RestControllerAdvice注解使用方法解析,@RestControllerAdvice是Controller的增強(qiáng) 常用于全局異常的捕獲處理 和請求參數(shù)的增強(qiáng),需要的朋友可以參考下2024-01-01
Spring boot創(chuàng)建自定義starter的完整步驟
這篇文章主要給大家介紹了關(guān)于Spring boot創(chuàng)建自定義starter的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09

