跨站点脚本编制 - SpringBoot配置XSS过滤器(基于mica-xss)

时间:2024-03-09 17:01:18

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