有时网站为了美观,会允许用户输入一些富文本,这样在显示的时候,就可以显示的更友好。虽然在输入富文本的时候在客户端进行了控制,但是,仍然难易避免一些攻击者通过抓包篡改数据绕过客户端的控制。因此,在服务器端收到富文本的数据之后,还是要进行净化处理。
在写具体的解决方案之前,分别通过讯飞的星火系统进行了测试,回答如下:
回复说答案不对,重新再回答时,回答的依然是一模一样的。 最关键的是第二条解决方案明显不合适,“2.对特殊字符进行转义:对于HTML标记、脚本语言等特殊字符,需要对其进行转义,以防止它们被浏览器解析为有意义的内容。例如,将<
替换为<
,将>
替换为>
,将"
替换为"
等。” 富文本是不能进行这种转换的,否则,富文本就不是富文本了,就变成文本了。所以,答案是错误的。
再尝试一下,chatgpt,同样的问题,答复如下:
关于ChatGpt的回答也出现在第二条上有一些问题:“输出过滤:在将富文本内容显示在页面上时,应该使用HTML过滤器和转义函数等安全措施来过滤和转义特殊字符,以避免恶意脚本代码被执行。 ”, 这里说的也没有具体说明哪些字符要转义。
于是进一步追问: 要转移哪些字符?
其实,单引号和双引号转义会导致一些问题的,例如,富文本输入时,会带有标签的属性,而这些属性的值,一般都会使用单引号或者双引号。所以,转义在处理富文本时,一般不建议使用。
其实,星火和chatgpt给出的第一条是一般都采用的解决方案,就是过滤不安全的html标签【例如:script等】和某些危险的属性【例如:onclick等】。
对于过滤业界也有一些比较成熟的库可以使用:
1) antisamy,OWASP AntiSamy | OWASP Foundation
这个由OWASP提供的库,提供过滤HTML标签和属性的功能,提供了丰富的policy。具体实现代码可以参考:GitHub - OWASP/java-html-sanitizer: Takes third-party HTML and produces HTML that is safe to embed in your web application. Fast and easy to configure.
2) googlecode里的owasp java html sanitizer
提供了一个基础的策略,可以基于这个基础策略进行修改,使用的是owasp的policy builder类:org.owasp.html.HTMLPolicyBuilder,通过allowAttributes和allowElements添加支持的标签和属性。经过测试默认的策略里,img标签是不支持src是base64格式的数据的,所以如果想支持
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
e就必须要修改默认的策略img的src属性的正则表达式才可以,通过添加属性是不可以的。
另外还需要注意的一点是,在净化的时候,会修改原来的HTML结构,如果某些标签不完整,Sainitizer会将标签补充完整,例如:
<th scope="group">data</th>
净化之后:
<table><tbody><th scope="group">data</th> </tbody></table>
<li class="test">data </li>
净化之后:
<ul><li class="test">data </li></ul>
具体的库可以参考:
https://mvnrepository.com/artifact/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer
3)使用jsoup的库
默认SafeList定义了一个Basic的策略可以满足一般的需求,Basic的策略支持的标签和属性如下:
This safelist allows a fuller range of text nodes: a, b, blockquote, br, cite, code, dd, dl, dt, em, i, li, ol, p, pre, q, small, span, strike, strong, sub, sup, u, ul, and appropriate attributes.
Links (a elements) can point to http, https, ftp, mailto, and have an enforced rel=nofollow attribute.
示例代码:
String unsafe =
"<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Safelist.basic());
// now: <p><a href="http://example.com/" rel="nofollow">Link</a></p>
如果有特殊需求,可以通过SafeList的addTags和addAttributes 添加需要支持的标签和属性。
关于jsoup的具体信息可以参考:Prevent cross site scripting with jsoup。