1. 簡介
XSS,即跨站腳本編制,英文為Cross Site Scripting。為了和CSS區分,命名為XSS。
XSS是最普遍的Web應用安全漏洞。這類漏洞能夠使得攻擊者嵌入惡意腳本代碼到正常用戶會訪問到的頁面中,當正常用戶訪問該頁面時,則可導致嵌入的惡意腳本代碼的執行,從而達到惡意攻擊用戶的目的。
2. XSS相關博客
跨站點腳本編制 - SpringBoot配置XSS過濾器(基於Jsoup)
3. 其他安全相關博客
SQL盲注、SQL注入 - SpringBoot配置SQL注入過濾器
跨站點請求偽造 - SpringBoot配置CSRF過濾器
4. 基於mica-xss解決
參考:https://gitee.com/596392912/mica
- pom.xml添加依賴
<dependency>
<groupId>net.dreamlu</groupId>
<artifactId>mica-core</artifactId>
<version>2.0.9-GA</version>
</dependency>
<dependency>
<groupId>net.dreamlu</groupId>
<artifactId>mica-xss</artifactId>
<version>2.0.9-GA</version>
</dependency>
添加依賴后,已經完成了XSS過濾配置。
5. 測試
- 編寫測試Controller
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用戶Controller
*
* @author CL
*
*/
@RestController
@RequestMapping(value = "user")
public class UserController {
/**
* 獲取用戶信息
*
* @param user 用戶Entity
* @return
*/
@RequestMapping(value = "get")
public String get(User user) {
return user.toString();
}
}
/**
* 用戶Entity
*
* @author CL
*
*/
class User {
/**
* 用戶ID
*/
private String id;
/**
* 用戶名稱
*/
private String username;
public User() {
super();
}
public User(String id, String username) {
super();
this.id = id;
this.username = username;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + "]";
}
}
- 跳過過濾
在Controller上添加注解@XssCleanIgnore
即可。
/**
* 注冊Controller
*
* @author CL
*
*/
@XssCleanIgnore
@RestController
@RequestMapping(value = "register")
public class RegisterController {
/**
* 獲取信息
*
* @param username 用戶名稱
* @return
*/
@RequestMapping(value = "get")
public String get(String username) {
return username;
}
}
- Postman測試
6. mica-xss原理
- 自定義WebDataBinder過濾Form表單
WebDataBinder的作用是從request將請求中的parameters綁定到對應的JavaBean上,在Controller方法中的參數類型可以是基本類型,也可以是普通Java類型。SpringMVC提供了在綁定的過程中用戶自定義編輯綁定的接口,因此可以在綁定過程中進行過濾。
/**
* 表單 xss 處理
*
* @author L.cm
*/
@AutoIgnore
@ControllerAdvice
@RequiredArgsConstructor
public class FormXssClean {
private final XssCleaner xssCleaner;
@InitBinder
public void initBinder(WebDataBinder binder) {
// 處理前端傳來的表單字符串
binder.registerCustomEditor(String.class, new StringPropertiesEditor(xssCleaner));
}
//......
}
- 自定義JsonDeserializer(反序列化)過濾Json
SpringBoot中默認是使用Jackson對Json數據進行序列化和反序列化,也可以自定義JsonSerializer和JsonDeserializer類自主實現。用戶提交的Json報文會通過JsonDeserializer綁定到Java Bean中。因此可以在JsonDeserializer中進行過濾。
/**
* jackson xss 處理
*
* @author L.cm
*/
@Slf4j
@RequiredArgsConstructor
public class JacksonXssClean extends JsonDeserializer<String> {
private final XssCleaner xssCleaner;
@Override
public String deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
// XSS filter
String text = p.getValueAsString();
if (text == null) {
return null;
} else if (XssHolder.isEnabled()) {
String value = xssCleaner.clean(text);
log.debug("Json property value:{} cleaned up by mica-xss, current value is:{}.", text, value);
return value;
} else {
return text;
}
}
}
- XssUtil
mica-xss的XSS工具類其實也是基於Jsoup工具實現的。
/**
* xss clean
*
* <p>
* 參考自 jpress:https://gitee.com/fuhai/jpress
* </p>
*
* @author L.cm
* @author michael
*/
public class XssUtil {
private static final HtmlWhitelist WHITE_LIST = new HtmlWhitelist();
/**
* xss 清理
*
* @param html html
* @return 清理后的 html
*/
public static String clean(String html) {
if (StringUtils.hasText(html)) {
return Jsoup.clean(html, WHITE_LIST);
}
return html;
}
//......
}
7. mica.xss配置
mica-xss提供的配置類如下:
/**
* Xss配置類
*
* @author L.cm
*/
@Getter
@Setter
@ConfigurationProperties("mica.xss")
public class MicaXssProperties {
/**
* 開啟xss
*/
private boolean enabled = true;
/**
* 攔截的路由,默認為空
*/
private List<String> pathPatterns = new ArrayList<>();
/**
* 放行的規則,默認為空
*/
private List<String> excludePatterns = new ArrayList<>();
}
可以看出,默認是開啟XSS過濾的,我們可以通過application配置文件,來開啟或關閉過濾,並指定相應的攔截路由(默認為全部:/**)和放行規則(默認為空)。
如果默認的配置已經滿足需求,則不需要再自定義配置mica.xss。
mica:
xss:
enabled: true
excludePatterns:
- /login
- /logout