我在做一个评论功能,用户提交的内容会直接用 innerHTML 插入到页面上。虽然我知道可以用 DOMPurify 这类库来过滤,但想先自己试试简单处理。比如把 < 转成 < 之类的。但发现如果用户输入的是带样式的文本,比如下面这段 CSS,还是会生效,是不是有风险?
.malicious {
background: url('javascript:alert(1)');
color: red;
}
这种通过 CSS 注入脚本的情况算 XSS 吗?我该怎么防?只转义 HTML 标签够不够?
只转义 HTML 标签是不够的,你得考虑全面的防御措施。除了 HTML 标签,你还得处理各种可能的事件处理器,以及像你例子中的样式注入。
一个简单的做法是,可以考虑使用
textContent或者innerText来代替innerHTML。这样插入的内容会被当作纯文本处理,不会被解析为 HTML 或 CSS。如果你真的需要渲染 HTML 内容,除了手动转义,推荐使用专门的库,比如 DOMPurify,它能帮你处理复杂的场景,包括 CSS 注入的风险。不过,自己动手的话,你至少得做以下几个步骤:
1. 转义 HTML 实体,不仅仅是
<和>,还有&、"、'等。2. 清理掉所有事件处理器,比如
onclick、onmouseover等。3. 对 CSS 样式进行严格的白名单过滤,只允许特定的安全属性和值。
举个简单的转义例子:
但记住,手动实现这些逻辑很容易遗漏,所以尽量使用成熟的库来处理这些安全问题。