springboot解決XSS存儲(chǔ)型漏洞問(wèn)題
XSS攻擊
XSS 攻擊
跨站腳本攻擊(Cross Site Scripting),為不和 前端層疊樣式表(Cascading Style Sheets)CSS 混淆,故將跨站腳本攻擊縮寫(xiě)為 XSS。
XSS(跨站腳本攻擊)
是指惡意攻擊者往 Web 頁(yè)面里插入惡意 Script 代碼,當(dāng)用戶(hù)瀏覽該頁(yè)時(shí),嵌入其中 Web 里面的 Script 代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶(hù)的目的。
類(lèi)似于 sql 注入。是目前最普遍的 Web 應(yīng)用安全漏洞,也是 Web 攻擊中最常見(jiàn)的攻擊方式之一。
XSS( 跨站腳本攻擊)攻擊通常指的是通過(guò)利用網(wǎng)頁(yè)開(kāi)發(fā)時(shí)留下的漏洞,通過(guò)巧妙的方法注入惡意指令代碼到網(wǎng)頁(yè),使用戶(hù)加載并執(zhí)行攻擊者惡意制造的網(wǎng)頁(yè)程序。
這些惡意網(wǎng)頁(yè)程序通常是 JavaScript,但實(shí)際上也可以包括 Java、 VBScript、ActiveX、 Flash 或者甚至是普通的 HTML。
攻擊成功后,攻擊者可能得到包括但不限于更高的權(quán)限(如執(zhí)行一些操作)、私密網(wǎng)頁(yè)內(nèi)容、會(huì)話(huà)和 cookie 等各種內(nèi)容。
XSS攻擊示例
過(guò)濾請(qǐng)求非法內(nèi)容XSS類(lèi):XssRequestWrappers
這個(gè)類(lèi)用來(lái)過(guò)濾請(qǐng)求非法內(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)簽,支持單引號(hào)和雙引號(hà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...>開(kāi)頭的標(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:"開(kāi)頭的字符串 scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // 移除以"vbscript:"開(kāi)頭的字符串 scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // 移除以"onload..."開(kāi)頭的字符串 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; } }
定義過(guò)濾器監(jiān)聽(tīng)XSSFilter 重寫(xiě)Filter
在這個(gè)過(guò)濾器中監(jiān)聽(tīng)XSSFilter,使用上面寫(xiě)的XssRequestWrappers來(lái)處理請(qǐng)求中的非法內(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); } }
注冊(cè)這個(gè)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("/*"); // 這里配置需要過(guò)濾的URL registrationBean.setName("xssFilter"); registrationBean.setOrder(1); // 設(shè)置過(guò)濾器的執(zhí)行順序,數(shù)字越小越優(yōu)先 return registrationBean; } }
執(zhí)行這三步應(yīng)該就可以了,不過(guò)啟動(dòng)可能會(huì)報(bào)錯(cuò),如果報(bào)錯(cuò)添加以下依賴(lài)即可:
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
到這里XSS存儲(chǔ)型漏洞應(yīng)該就能解決了
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring MVC 文件、cookies的接收 與REST響應(yīng)詳
在SpringMVC中,使用@RequestPart注解可接收文件并處理多部分請(qǐng)求,同時(shí)可以通過(guò)@CookieValue和HttpServletResponse來(lái)獲取和設(shè)置Cookies,本文介紹Spring MVC 文件、cookies的接收 與REST響應(yīng),感興趣的朋友跟隨小編一起看看吧2024-09-09看過(guò)就懂的java零拷貝及實(shí)現(xiàn)方式詳解
這篇文章主要為大家詳細(xì)的介紹了什么是零拷貝,傳統(tǒng)的IO執(zhí)行流程,零拷貝相關(guān)的知識(shí)點(diǎn)回顧,零拷貝實(shí)現(xiàn)的幾種方式及java提供的零拷貝方式相關(guān)內(nèi)容,有需要的朋友可以借鑒參考下2022-01-01SpringBoot實(shí)現(xiàn)登錄攔截器的方法詳解
其實(shí)spring?boot攔截器的配置方式和springMVC差不多,只有一些小的改變需要注意下就ok了。本文主要給大家介紹了關(guān)于如何在Springboot實(shí)現(xiàn)登陸攔截器功能,需要的朋友可以參考下2022-07-07JDK1.6“新“特性Instrumentation之JavaAgent(推薦)
這篇文章主要介紹了JDK1.6“新“特性Instrumentation之JavaAgent,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08SpringBoot統(tǒng)計(jì)、監(jiān)控SQL運(yùn)行情況的方法詳解
這篇文章主要給大家介紹了關(guān)于SpringBoot統(tǒng)計(jì)、監(jiān)控SQL運(yùn)行情況的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-02-02javamail實(shí)現(xiàn)注冊(cè)激活郵件
這篇文章主要為大家詳細(xì)介紹了javamail實(shí)現(xiàn)注冊(cè)激活郵件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04你必須得會(huì)的SpringBoot全局統(tǒng)一處理異常詳解
程序在運(yùn)行的過(guò)程中,不可避免會(huì)產(chǎn)生各種各樣的錯(cuò)誤,這個(gè)時(shí)候就需要進(jìn)行異常處理,本文主要為大家介紹了SpringBoot實(shí)現(xiàn)全局統(tǒng)一處理異常的方法,需要的可以參考一下2023-06-06