这足以防止 xss 吗?

Is this enough to prevent xss?

我在一个网站上工作,那里会有很多用户生成的内容。作为一个所见即所得的编辑器,我使用的是 tinyMCE。作为模板引擎,我使用 ejs。 为了防止 XSS 我决定使用 xss npm 包。 我正在使用这些自定义规则:

const strict = {
  whiteList: {},
}

const withTags = {
  whiteList: {
    div: [],
    strong: [],
    em: [],
    br: [],
    ul: [],
    li: [],
    ol: [],
    blockquote: [],
  },
}

假设用户使用文本区域并提交此代码:

<script>alert("hi")</script>

在我的数据库中,它是这样保存的:

&lt;script&gt;alert("hi")&lt;/script&gt;

现在,当内容由 ejs 呈现时,一些内容使用转义输出呈现 (<%= %>)。呈现的转义输出(html 页面)如下所示:

&lt;script&gt;console.log("test")&lt;/script&gt;

但是,某些内容是使用 ejs 未转义的原始输出 (<%- %>) 呈现的。 Html 看起来像这样:

<script>console.log("test")</script>

我有两个问题:

  1. 因为 < 和 > 被转义为 &lt;&gt; 渲染 ejs 未转义的输出是否安全?
  2. 我所做的通常足以进行 XSS 保护吗?

非常感谢!

首先,您的数据可能没有按照您提供的方式保存在数据库中。它很可能在没有任何编码的情况下存储在那里(应该是这样)。

EJS 本身在正确使用时会为您处理编码输出,以便您可以安全地构造参数化 HTML。但在你的情况下,你想禁用此保护以呈现原始 HTML,所以是的,你必须小心。您可以使用几个安全控件。

1. DOMPurify

我个人没有使用过xss 库,它似乎有很多下载并且可能是一个不错的选择。但是 DOMPurify 可能更好。它也不需要配置,并且内置了对可信类型的支持(我稍后会讲到)。

你会用它两次。首先在服务器端,当 HTML 由用户提交时,其次在客户端,当 HTML 由 EJS 呈现时。

如果您非常重视安全性,那么您会将来自服务器端净化的异常警报连接到您的 SIEM/SOC 等。然后您就会知道何时有人试图对您的网站进行 XSS 攻击。

2。沙盒 Iframes

您可以实施的另一个客户端控件是沙盒 iframe。您不是只在页面上呈现 HTML,而是创建一个 IFRAME,为其提供正确配置的 sandbox 属性,然后将净化后的 HTML 设置为内容。现在就算净化出了问题,恶意HTML也会被孤立在自己的世界里

3。内容安全策略

最酷且(如果使用得当)最有效的 XSS 防护是 CSP。它是如何工作的,你给你的网站限制,比如“不要执行脚本”,“不要加载图像”,等等。然后你允许你想要执行的脚本,没有别的。现在,如果攻击者设法在页面上注入脚本、link、表单等,它将无法工作,因为它没有被特别允许。

我已经写了很长的关于 CSP 的文章 here, you will even find specific examples for your case (NodeJS and EJS) with CodeSandbox examples on that article. And in general about XSS protection you can read more here

希望对您有所帮助!