本人在做某項目中,存在通過電子郵件模板消息存儲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>'
會正常顯示