javascript - 如何安全地接受包含来自所见即所得编辑器的 iframe 的用户输入?

标签 javascript node.js iframe tinymce

我正在使用 TinyMCE WYSIWYG 编辑器来允许用户输入富文本。

用户可以在编辑器中粘贴富媒体链接。编辑器会自动检测这些并创建一个 iframe。例如,如果您粘贴 YouTube 链接,则会出现嵌入的 YouTube 视频。用户可以将编辑器的内容发布为帖子,其他用户可以看到。

我正在使用 DOMPurify 来清理输入。由于 XSS 问题,它(正确地)删除了所有 iframe。虽然我可以将 iframe 列入白名单,但我对此犹豫不决。

我的问题是:我如何安全接受这些 iframe,然后将它们呈现给其他用户查看/交互?

最佳答案

在网上找不到任何清晰明显的解决方案,但我想我想出了一些不错的解决方案。以下是我如何允许用户安全地提交 iframe。

首先,我只是joi验证库对输入执行一些基本验证,例如它是一个字符串吗?

接下来,我使用DOMPurify清理用户提交的 html。通常,DOMPurify 会查找并删除所有 iframe,因为它们可能被恶意使用。但是,您可以将 iframe 添加到白名单中。但是,您不想允许每个 iframe 属性。有些可以被恶意用户用来执行 javascript,例如“onalert”和“onerror”。出于我的目的,我想要允许的唯一属性是“src”、“allowfullscreen”和“scrolling”。将 iframe 添加到 DOMPurify 白名单时,您还需要显式声明允许哪些属性。

    req.body.input = DOMPurify.sanitize(req.body.input, { ADD_TAGS: ["iframe"], ADD_ATTR: ['allowfullscreen', 'scrolling'] });

有两点需要注意:

  • 请务必使用“ADD_TAGS”而不是“ALLOWED_TAGS”。 “ADD_TAGS”将标签添加到现有白名单中。 “ALLOWED_TAGS”表示允许引用的标记。
  • 我没有明确提到“src”作为可接受的属性。不知道为什么,但它似乎只是允许这样做。

接下来,为了增加安全性,我决定添加 sandbox属性到每个 iframe。此属性对框架中的内容应用额外的限制。为此,我使用了 cheerio轻松解析和操作 HTML 输入。以下是我如何找到每个 iframe,添加 sandbox 属性,并将其值设置为“allow-same-origin allowed-scripts”,从而解除对这两个限制的限制。我为什么举起它们?因为我的 iframe 内容(例如 YouTube 视频)需要它才能正常运行。

    let inputCheerio = cheerio.load(req.body.input);
    inputCheerio('iframe').attr('sandbox', 'allow-same-origin allow-scripts');
    req.body.input = inputCheerio.html();

最后,为了增加另一层安全性,我对 Content Security Policy 进行了更改(CSP) 用于显示此内容的页面。具体来说,我设置了frame-src指令仅允许 iframe 内容的某些有效来源。例如:

    res.setHeader("Content-Security-Policy", "frame-src https://youtube.com");

请注意,实际的 CSP 会更长。这只是使用frame-src指令的一个示例。

我不确定这是否是实现我想要的最安全的方式,但这是我目前能想到的最好的方式。请随时纠正我或补充我的答案。希望有人觉得这很有用。

关于javascript - 如何安全地接受包含来自所见即所得编辑器的 iframe 的用户输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68274122/

相关文章:

javascript - 从路径字符串构建嵌套文件夹结构

javascript - 如何使用 mongoose 操作从 mongo db 返回的数据

php - IRC 用户名作为论坛用户名

javascript - 如何拖动 div 并使光标保持在单击它时的同一位置?

javascript - 生成页面后将 target _blank 添加到链接

javascript - 如何将字符串数组中每个单词的第一个字母大写?写入 `for ... of ... loop ` (ES6)

javascript - node.js:如何在尝试解析内容之前等到 "unzip"完成

python - 在node.JS中使用POST上传两个文件

google-maps - 通过 SSL 的 Google map 选项

javascript - 表单不传递 iframe 输入