本人在做某项目中,存在通过电子邮件模板消息存储XSS,因为前端使用富文本编辑框编辑html,但在后端保存的时候,并没有进行xss过滤,因此存在xss问题。
经过研究,本项目使用https://github.com/OWASP/java-html-sanitizer清理所有包含html标记的字段,这些字段可以防止xss攻击。
public class HtmlUtil {
private static final AttributePolicy INTEGER =
new AttributePolicy() {
@Override
@Autowired
public String apply(
final String elementName, final String attributeName, final String value) {
final int n = value.length();
if (n == 0) {
return null;
} else {
for (int i = 0; i < n; ++i) {
final char ch = value.charAt(i);
if (ch == '.') {
if (i == 0) {
return null;
}
return value.substring(0, i);
}
if ('0' > ch || ch > '9') {
return null;
}
}
return value;
}
}
};
private static final PolicyFactory IMAGES =
(new HtmlPolicyBuilder())
.allowUrlProtocols("http", "https", "data")
.allowElements("img")
.allowAttributes("alt", "src")
.onElements("img")
.allowAttributes("border", "height", "width")
.matching(INTEGER)
.onElements("img")
.toFactory();
// add 'target' attributes which allows open link in a new window
private static final PolicyFactory LINKS =
(new HtmlPolicyBuilder())
.allowStandardUrlProtocols()
.allowElements("a")
.allowAttributes("href", "target")
.onElements("a")
.requireRelNofollowOnLinks()
.toFactory();
/*
E.g.
case1 '<a href="javascript:prompt(document.domain);//">click</a>'
A tag will be sanitized and only 'click' will be returned.
case2 '<a href="https://www.google.com/">google</a>'
Nothing will be changed, and '<a href="https://www.google.com/">google</a>' will be returned since the policy specified with Sanitizers.LINKS.
Referenced from:
https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20190325.1/org/owasp/html/Sanitizers.html
*/
public static String stripXss(String value) {
if (value != null) {
final PolicyFactory policy =
Sanitizers.FORMATTING
.and(LINKS)
.and(Sanitizers.BLOCKS)
.and(Sanitizers.TABLES)
.and(IMAGES)
.and(Sanitizers.STYLES);
value = policy.sanitize(value);
}
return value;
}
}
在相应字段的set、get方法加上xss过滤。若有构造函数,该字段也要加上过滤
public void setBody(final String body) {
this.body = HtmlUtil.stripXss(body);
}
public String getBody() {
return HtmlUtil.stripXss(body);
}
举例:
E.g.
case1 '<a href="javascript:prompt(document.domain);//">click</a>'
A tag will be sanitized and only 'click' will be returned.
case2 '<a href="https://www.google.com/">google</a>'
会正常显示