【快學SpringBoot】過濾XSS腳本攻擊(包括json格式)


若圖片查看異常,請前往掘金查看:https://juejin.im/post/5d079e555188251ad81a28d9

XSS攻擊是什么

XSS攻擊全稱跨站腳本攻擊,是為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS,XSS是一種在web應用中的計算機安全漏洞,它允許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。

簡而言之,就是作惡用戶通過表單提交一些前端代碼,如果不做處理的話,這些前端代碼將會在展示的時候被瀏覽器執行。

如何避免XSS攻擊

解決XSS攻擊,可以通過后端對輸入的數據做過濾或者轉義,使XSS攻擊代碼失效。

代碼實現

對於過濾XSS腳本的代碼,通過搜索引擎可以搜索到很多,但似乎都不是那么全面。基本上都是只能過濾querystring(表單類型)類型的入參,而不能過濾json類型的入參。其實,在現在的開發中,更多的是使用json類型做數據交互。下面就直接貼代碼了:

新建XssAndSqlHttpServletRequestWrapper.java

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
 * @author Happy
 * 防止XSS攻擊
 */
public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {
 private HttpServletRequest request;
 public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {
 super(request);
 this.request = request;
 }
 @Override
 public String getParameter(String name) {
 String value = request.getParameter(name);
 if (!StringUtils.isEmpty(value)) {
 value = StringEscapeUtils.escapeHtml4(value);
 }
 return value;
 }
 @Override
 public String[] getParameterValues(String name) {
 String[] parameterValues = super.getParameterValues(name);
 if (parameterValues == null) {
 return null;
 }
 for (int i = 0; i < parameterValues.length; i++) {
 String value = parameterValues[i];
 parameterValues[i] = StringEscapeUtils.escapeHtml4(value);
 }
 return parameterValues;
 }
}

這里重寫了兩個方法:getParameter和getParameterValues,getParameter方法是直接通過request獲得querystring類型的入參調用的方法。如果是通過springMVC注解類型來獲得參數的話,走的是getParameterValues的方法。大家可以通過打印一個輸出來驗證一下。

StringEscapeUtils.escapeHtml4這個方法來自Apache的工具類,maven坐標如下:

<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-text</artifactId>
 <version>1.4</version>
</dependency>

新建XssFilter.java

過濾的代碼寫完了,下面就是在一個filter中應用該代碼。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
 * @author Happy
 */
@WebFilter
@Component
public class XssFilter implements Filter {
 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
 }
 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
 throws IOException, ServletException {
 HttpServletRequest req = (HttpServletRequest) request;
 XssAndSqlHttpServletRequestWrapper xssRequestWrapper = new XssAndSqlHttpServletRequestWrapper(req);
 chain.doFilter(xssRequestWrapper, response);
 }
 @Override
 public void destroy() {
 }
 /**
 * 過濾json類型的
 * @param builder
 * @return
 */
 @Bean
 @Primary
 public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) {
 //解析器
 ObjectMapper objectMapper = builder.createXmlMapper(false).build();
 //注冊xss解析器
 SimpleModule xssModule = new SimpleModule("XssStringJsonSerializer");
 xssModule.addSerializer(new XssStringJsonSerializer());
 objectMapper.registerModule(xssModule);
 //返回
 return objectMapper;
 }
}

過濾表單類型的代碼已經完成(xssObjectMapper這個是后面過濾json類型才用到的)。下面來實現過濾json類型的代碼:

新建XssStringJsonSerializer.java

代碼如下:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.text.StringEscapeUtils;
import java.io.IOException;
public class XssStringJsonSerializer extends JsonSerializer<String> {
 @Override
 public Class<String> handledType() {
 return String.class;
 }
 @Override
 public void serialize(String value, JsonGenerator jsonGenerator,
 SerializerProvider serializerProvider) throws IOException {
 if (value != null) {
 String encodedValue = StringEscapeUtils.escapeHtml4(value);
 jsonGenerator.writeString(encodedValue);
 }
 }
}

這里是通過修改SpringMVC的json序列化來達到過濾xss的目的的。其實也可以通過第一種方法,重寫getInputStream方法來實現,這里我就不做演示了(通過json類型傳參會走getInputStream方法,通過重寫該方法打印輸出可以證明)。

測試

TestController.java

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
 * @author Happy
 */
@RestController
@RequestMapping(value = "/test")
public class TestController {
 @PostMapping(value = "/xss")
 public Object test(String name) {
 System.out.println(name);
 return name;
 }
 @PostMapping(value = "/json")
 public Object testJSON(@RequestBody Param param) {
 return param;
 }
 @GetMapping(value = "/query")
 public Object testQuery(String q){
 return q;
 }
 @PostMapping(value = "/upload")
 public Object upload(MultipartFile file){
 System.out.println(file.getOriginalFilename());
 return "OK";
 }
}

下面通過postman測試下效果:

【快學springboot】15、SpringBoot過濾XSS腳本攻擊

【快學springboot】15、SpringBoot過濾XSS腳本攻擊

【快學springboot】15、SpringBoot過濾XSS腳本攻擊

可以看到,js代碼已經經過轉義。轉義過后的代碼,即使前端讀取過去了,也不會被瀏覽器執行的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM