SpringBoot利用filter實(shí)現(xiàn)xss防御功能
1.什么是xss?
Cross-Site Scripting(跨站腳本攻擊)簡(jiǎn)稱 XSS,是一種代碼注入攻擊。攻擊者通過(guò)在目標(biāo)網(wǎng)站上注入惡意腳本,使之在用戶的瀏覽器上運(yùn)行。利用這些惡意腳本,攻擊者可獲取用戶的敏感信息如 Cookie、SessionID 等,進(jìn)而危害數(shù)據(jù)安全。 為了和 CSS 區(qū)分,這里把攻擊的第一個(gè)字母改成了 X,于是叫做 XSS。 XSS 的本質(zhì)是:惡意代碼未經(jīng)過(guò)濾,與網(wǎng)站正常的代碼混在一起;瀏覽器無(wú)法分辨哪些腳本是可信的,導(dǎo)致惡意腳本被執(zhí)行。 而由于直接在用戶的終端執(zhí)行,惡意代碼能夠直接獲取用戶的信息,或者利用這些信息冒充用戶向網(wǎng)站發(fā)起攻擊者定義的請(qǐng)求。 在部分情況下,由于輸入的限制,注入的惡意腳本比較短。但可以通過(guò)引入外部的腳本,并由瀏覽器執(zhí)行,來(lái)完成比較復(fù)雜的攻擊策略。 這里有一個(gè)問(wèn)題:用戶是通過(guò)哪種方法“注入”惡意腳本的呢? 不僅僅是業(yè)務(wù)上的“用戶的 UGC 內(nèi)容”可以進(jìn)行注入,包括 URL 上的參數(shù)等都可以是攻擊的來(lái)源。在處理輸入時(shí),以下內(nèi)容都不可信:
- 來(lái)自用戶的 UGC 信息
- 來(lái)自第三方的鏈接
- URL 參數(shù)
- POST 參數(shù)
- Referer (可能來(lái)自不可信的來(lái)源)
- Cookie (可能來(lái)自其他子域注入)
XSS 分類
根據(jù)攻擊的來(lái)源,XSS 攻擊可分為存儲(chǔ)型、反射型和 DOM 型三種。 |類型|存儲(chǔ)區(qū)
|插入點(diǎn)
| |-|-| |存儲(chǔ)型 XSS|后端數(shù)據(jù)庫(kù)|HTML| |反射型 XSS|URL|HTML| |DOM 型 XSS|后端數(shù)據(jù)庫(kù)/前端存儲(chǔ)/URL|前端 JavaScript|
- 存儲(chǔ)區(qū):惡意代碼存放的位置。
- 插入點(diǎn):由誰(shuí)取得惡意代碼,并插入到網(wǎng)頁(yè)上。
存儲(chǔ)型 XSS
存儲(chǔ)型 XSS 的攻擊步驟:
- 攻擊者將惡意代碼提交到目標(biāo)網(wǎng)站的數(shù)據(jù)庫(kù)中。
- 用戶打開目標(biāo)網(wǎng)站時(shí),網(wǎng)站服務(wù)端將惡意代碼從數(shù)據(jù)庫(kù)取出,拼接在 HTML 中返回給瀏覽器。
- 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行。
- 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作。
這種攻擊常見于帶有用戶保存數(shù)據(jù)的網(wǎng)站功能,如論壇發(fā)帖、商品評(píng)論、用戶私信等。
反射型 XSS
反射型 XSS 的攻擊步驟:
- 攻擊者構(gòu)造出特殊的 URL,其中包含惡意代碼。
- 用戶打開帶有惡意代碼的 URL 時(shí),網(wǎng)站服務(wù)端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器。
- 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行。
- 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作。
反射型 XSS 跟存儲(chǔ)型 XSS 的區(qū)別是:存儲(chǔ)型 XSS 的惡意代碼存在數(shù)據(jù)庫(kù)里,反射型 XSS 的惡意代碼存在 URL 里。 反射型 XSS 漏洞常見于通過(guò) URL 傳遞參數(shù)的功能,如網(wǎng)站搜索、跳轉(zhuǎn)等。 由于需要用戶主動(dòng)打開惡意的 URL 才能生效,攻擊者往往會(huì)結(jié)合多種手段誘導(dǎo)用戶點(diǎn)擊。 POST 的內(nèi)容也可以觸發(fā)反射型 XSS,只不過(guò)其觸發(fā)條件比較苛刻(需要構(gòu)造表單提交頁(yè)面,并引導(dǎo)用戶點(diǎn)擊),所以非常少見。
DOM 型 XSS
DOM 型 XSS 的攻擊步驟:
- 攻擊者構(gòu)造出特殊的 URL,其中包含惡意代碼。
- 用戶打開帶有惡意代碼的 URL。
- 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,前端 JavaScript 取出 URL 中的惡意代碼并執(zhí)行。
- 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作。
DOM 型 XSS 跟前兩種 XSS 的區(qū)別:DOM 型 XSS 攻擊中,取出和執(zhí)行惡意代碼由瀏覽器端完成,屬于前端 JavaScript 自身的安全漏洞,而其他兩種 XSS 都屬于服務(wù)端的安全漏洞。
XSS 攻擊的預(yù)防
通過(guò)前面的介紹可以得知,XSS 攻擊有兩大要素:
- 攻擊者提交惡意代碼。
- 瀏覽器執(zhí)行惡意代碼。
我們是否能夠在用戶輸入的過(guò)程,過(guò)濾掉用戶輸入的惡意代碼呢?
- 輸入過(guò)濾
- 預(yù)防存儲(chǔ)型和反射型 XSS 攻擊
- 純前端渲染
- 轉(zhuǎn)義 HTML
- 預(yù)防 DOM 型 XSS 攻擊
2.代碼工程
實(shí)驗(yàn)?zāi)繕?biāo)
利用過(guò)濾器實(shí)現(xiàn)xss攔截
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springboot-demo</artifactId> <groupId>com.et</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>xss</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency> </dependencies> </project>
controller
package com.et.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController public class HelloWorldController { @RequestMapping("/hello") public Map<String, Object> showHelloWorld(){ Map<String, Object> map = new HashMap<>(); map.put("msg", "HelloWorld"); return map; } @RequestMapping("/api/xss") public void xssApiTest(String name, String content) { System.out.println("api->name:"+name); System.out.println("api->content:"+content); } /** * bu * @param name * @param content */ @RequestMapping("/ui/xss") public void xssUiTest(String name, String content) { System.out.println("ui->name:"+name); System.out.println("ui->content:"+content); } }
filter
具體攔截起的業(yè)務(wù)邏輯,你可以把你需要的攔截邏輯寫在這里
package com.et.filter; import org.apache.commons.lang3.StringUtils; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * @author Frank * */ public class XssFilter implements Filter { /** * excludes link */ List<String> excludes = new ArrayList<String>(); /** * xss filter switch */ public boolean enabled = false; @Override public void init(FilterConfig filterConfig) throws ServletException { String tempExcludes = filterConfig.getInitParameter("excludes"); String tempEnabled = filterConfig.getInitParameter("enabled"); if (StringUtils.isNotEmpty(tempExcludes)) { String[] url = tempExcludes.split(","); for (int i = 0; url != null && i < url.length; i++) { excludes.add(url[i]); } } if (StringUtils.isNotEmpty(tempEnabled)) { enabled = Boolean.valueOf(tempEnabled); } } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; if (handleExcludeURL(req, resp)) { chain.doFilter(request, response); return; } XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); chain.doFilter(xssRequest, response); } private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) { if (!enabled) { return true; } if (excludes == null || excludes.isEmpty()) { return false; } String url = request.getServletPath(); for (String pattern : excludes) { Pattern p = Pattern.compile("^" + pattern); Matcher m = p.matcher(url); if (m.find()) { return true; } } return false; } @Override public void destroy() { } } package com.et.filter; import org.jsoup.Jsoup; import org.jsoup.safety.Whitelist; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * XSS filter process * * @author Frank * */ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServletRequestWrapper(HttpServletRequest request) { super(request); } @Override public String[] getParameterValues(String name) { // Customize rules based on actual needs. Here, the content field is rich text and does not need to be filtered. if ("content".equals(name)) { return super.getParameterValues(name); } String[] values = super.getParameterValues(name); if (values != null) { int length = values.length; String[] escapseValues = new String[length]; for (int i = 0; i < length; i++) { // Prevent xss attacks and filter leading and trailing spaces escapseValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim(); } return escapseValues; } return super.getParameterValues(name); } }
config
配置xss攔截過(guò)濾器,并注冊(cè)到過(guò)濾鏈上
package com.et.config; import com.et.filter.XssFilter; import org.springframework.beans.factory.annotation.Value; import javax.servlet.DispatcherType; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map; /** * Filter config * @author Frank * */ @Configuration public class FilterConfig { @Value("${xss.enabled}") private String enabled; @Value("${xss.excludes}") private String excludes; @Value("${xss.urlPatterns}") private String urlPatterns; @SuppressWarnings({ "rawtypes", "unchecked" }) @Bean public FilterRegistrationBean xssFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setDispatcherTypes(DispatcherType.REQUEST); registration.setFilter(new XssFilter()); registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); registration.setName("xssFilter"); registration.setOrder(Integer.MAX_VALUE); Map<String, String> initParameters = new HashMap<String, String>(); initParameters.put("excludes", excludes); initParameters.put("enabled", enabled); registration.setInitParameters(initParameters); return registration; } }
application.yaml
server: port: 8088 xss: enabled: true # Exclude links (separate multiple links with commas) excludes: /ui/* # match links (separate multiple links with commas) urlPatterns: /api/*,/admin/*
代碼倉(cāng)庫(kù)
3.測(cè)試
啟動(dòng)Spring Boot應(yīng)用程序
使用postman測(cè)試
查看日志,發(fā)現(xiàn)name字段已經(jīng)過(guò)濾了
以上就是SpringBoot利用filter實(shí)現(xiàn)xss防御功能的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot filter xss防御的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java中unicode和中文相互轉(zhuǎn)換的簡(jiǎn)單實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇java中unicode和中文相互轉(zhuǎn)換的簡(jiǎn)單實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-08-08一個(gè)依賴搞定?Spring?Boot?接口防盜刷的流程分析
kk-anti-reptile 是適用于基于 spring-boot 開發(fā)的分布式系統(tǒng)的反爬蟲組件,這篇文章主要介紹了一個(gè)依賴搞定?Spring?Boot?接口防盜刷,需要的朋友可以參考下2022-06-06Mybatis-Plus中Mapper的接口文件與xml文件相關(guān)的坑記錄
這篇文章主要介紹了Mybatis-Plus中Mapper的接口文件與xml文件相關(guān)的坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Spring用AspectJ開發(fā)AOP(基于Annotation)
這篇文章主要介紹了Spring用AspectJ開發(fā)AOP(基于Annotation),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10SpringBoot整合Jasypt實(shí)現(xiàn)配置加密的步驟詳解
Jasypt是一個(gè)Java庫(kù),提供了一種簡(jiǎn)單的加密解密方式,可用于保護(hù)敏感數(shù)據(jù),例如密碼、API密鑰和數(shù)據(jù)庫(kù)連接信息等,本文給大家介紹了SpringBoot整合Jasypt實(shí)現(xiàn)配置加密的詳細(xì)步驟,感興趣的同學(xué)可以參考一下2023-11-11IDEA無(wú)法打開Marketplace的三種解決方案(推薦)
這篇文章主要介紹了IDEA無(wú)法打開Marketplace的三種解決方案(推薦),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11