springboot2.x使用Jsoup防XSS攻击的实现

时间:2021-05-19

后端应用经常接收各种信息参数,例如评论,回复等文本内容。除了一些场景下面,可以特定接受的富文本标签和属性之外(如:b,ul,li,h1, h2, h3...),需要过滤掉危险的字符和标签,防止xss攻击。

一、什么是XSS?

看完这个,应该有一个大致的概念。

XSS攻击常识及常见的XSS攻击脚本汇总
XSS过滤速查表

二、准则

  • 永远不要相信用户的输入和请求的参数(包括文字、上传等一切内容)
  • 参考第1条

三、实现做法

结合具体业务场景,对相应内容进行过滤,这里使用Jsoup。

jsoup是一款Java的HTML解析器。Jsoup提供的Whitelist(白名单)对文本内容进行过滤,过滤掉字符、属性,但是又保留必要的富文本格式。
如,白名单中允许b标签存在(并且不允许b标签带有其他属性)那么在一段Html内容,在过滤之后,会变成:

过滤前:

<b style="xxx" onclick="<script>alert(0);</script>">abc</>

过滤后:

<b>abc</b>

Whitelist主要方法说明

方法 说明 addAttributes(String tag, String... attributes) 给标签添加属性。Tag是属性名,keys对应的是一个个属性值。例如:addAttributes("a", "href", "class")表示:给标签a添加href和class属性,即允许标签a包含href和class属性。如果想给每一个标签添加一组属性,使用:all。例如:addAttributes(":all", "class").即给每个标签添加class属性。 addEnforcedAttribute(String tag, String attribute, String value) 给标签添加强制性属性,如果标签已经存在了要添加的属性,则覆盖原有值。tag:标签;key:标签的键;value:标签的键对应的值。例如:addEnforcedAttribute("a", "rel", "nofollow")表示 addProtocols(String tag, String key, String...protocols) 给URL属性添加协议。例如:addProtocols("a", "href", "ftp", "http", "https")标签a的href键可以指向的协议有ftp、http、https addTags(String... tags) 向Whitelist添加标签 basic() 允许的标签包括: a, b, blockquote, br, cite, code, dd, dl, dt, em, i, li, ol, p, pre, q, small, strike, strong, sub, sup, u, ul,以及合适的属性。标签a指向的连接可以是 http, https, ftp, mailto,转换完后会强制添加 rel=nofollow这个属性。不允许包含图片。 basicWithImages() 在basic的基础上增加了图片的标签:img以及使用src指向http或https类型的图片链接。 none() 只保留文本,其他所有的html内容均被删除 preserveRelativeLinks(booleanpreserve) false(默认):不保留相对地址的url;true:保留相对地址的url relaxed() 允许的标签:a, b, blockquote, br, caption, cite, code, col, colgroup, dd, dl, dt, em, h1, h2, h3, h4, h5, h6, i, img, li, ol, p, pre, q, small, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, u, ul。结果不包含标签rel=nofollow,如果需要可以手动添加。 simpleText() 只允许:b, em, i, strong, u。

四、例子

基于springboot

pom.xml依赖

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- jsoup --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.13.1</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> </dependencies>

HtmlFilter过滤类

import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.safety.Whitelist;import java.io.FileNotFoundException;import java.io.IOException;import java.util.List;/** * HtmlFilter * * @author 撸小鱼 * Created by lofish@foxmail.com on 2020-04-12 */public class HtmlFilter { /** * 默认使用relaxed() * 允许的标签: a, b, blockquote, br, caption, cite, code, col, colgroup, dd, dl, dt, em, h1, h2, h3, h4, h5, h6, i, img, li, ol, p, pre, q, small, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, u, ul。结果不包含标签rel=nofollow ,如果需要可以手动添加。 */ private Whitelist whiteList; /** * 配置过滤化参数,不对代码进行格式化 */ private Document.OutputSettings outputSettings; private HtmlFilter() { } /** * 静态创建HtmlFilter方法 * @param whiteList 白名单标签 * @param pretty 是否格式化 * @return HtmlFilter */ public static HtmlFilter create(Whitelist whiteList, boolean pretty) { HtmlFilter filter = new HtmlFilter(); if (whiteList == null) { filter.whiteList = Whitelist.relaxed(); } filter.outputSettings = new Document.OutputSettings().prettyPrint(pretty); return filter; } /** * 静态创建HtmlFilter方法 * @return HtmlFilter */ public static HtmlFilter create() { return create(null, false); } /** * 静态创建HtmlFilter方法 * @param whiteList 白名单标签 * @return HtmlFilter */ public static HtmlFilter create(Whitelist whiteList) { return create(whiteList, false); } /** * 静态创建HtmlFilter方法 * @param excludeTags 例外的特定标签 * @param includeTags 需要过滤的特定标签 * @param pretty 是否格式化 * @return HtmlFilter */ public static HtmlFilter create( List<String> excludeTags,List<String> includeTags, boolean pretty) { HtmlFilter filter = create(null, pretty); //要过滤的标签 if (includeTags != null && !includeTags.isEmpty()) { String[] tags = (String[]) includeTags.toArray(new String[0]); filter.whiteList.removeTags(tags); } //例外标签 if (excludeTags != null && !excludeTags.isEmpty()) { String[] tags = (String[]) excludeTags.toArray(new String[0]); filter.whiteList.addTags(tags); } return filter; } /** * 静态创建HtmlFilter方法 * @param excludeTags 例外的特定标签 * @param includeTags 需要过滤的特定标签 * @return HtmlFilter */ public static HtmlFilter create(List<String> excludeTags,List<String> includeTags) { return create( includeTags, excludeTags, false ); } /** * @param content 需要过滤内容 * @return 过滤后的String */ public String clean(String content) { return Jsoup.clean(content, "", this.whiteList, this.outputSettings); } public static void main(String[] args) throws FileNotFoundException, IOException { String text = "<a href=\"http:///a%22%20onclick=%22alert(1);%22%3Eabc%3C/a%3E%3Cscript%3Ealert(0);%3C/script%3E&abc=%3Cb%20style=%22xxx%22%20onclick=%22%3Cscript%3Ealert(0);%3C/script%3E%22%3Eabc%3C/%3E

到此这篇关于springboot2.x使用Jsoup防XSS攻击的实现的文章就介绍到这了,更多相关springboot2.x防XSS攻击内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章