javascript - 如何安全地接受包含来自 WYSIWYG 编辑器的 iframe 的用户输入?
问题描述
我正在使用 TinyMCE WYSIWYG 编辑器来允许用户输入富文本。
用户可以在编辑器中粘贴指向富媒体的链接。编辑器会自动检测到这些并创建一个 iframe。例如,如果您粘贴 YouTube 链接,则会显示嵌入的 YouTube 视频。用户可以将编辑器的内容发布为帖子,其他用户可以看到。
我正在使用 DOMPurify 来清理输入。由于 XSS 问题,它(正确地)删除了任何 iframe。虽然我可以将 iframe 列入白名单,但我对此犹豫不决。
我的问题是:我怎样才能安全地接受这些 iframe,然后将它们呈现给其他用户查看/交互?
解决方案
在网上找不到任何清晰明了的解决方案,但我想我想出了一些不错的东西。以下是我允许用户安全提交 iframe 的方法。
首先,我只是加入验证库来对输入执行一些基本验证,例如它是一个字符串吗?
接下来,我使用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”作为可接受的属性。不知道为什么,但它似乎还是允许它。
接下来,为了增加安全性,我决定将沙盒属性添加到每个 iframe。此属性对框架中的内容应用额外的限制。为此,我使用cheerio轻松解析和操作HTML 输入。以下是我找到每个 iframe、添加沙盒属性并将其值设置为“allow-same-origin allow-scripts”的方法,从而解除了对这两个限制的限制。我为什么要抬起它们?因为我的 iframe 的内容(例如 YouTube 视频)需要它才能正常运行。
let inputCheerio = cheerio.load(req.body.input);
inputCheerio('iframe').attr('sandbox', 'allow-same-origin allow-scripts');
req.body.input = inputCheerio.html();
最后,为了增加另一层安全性,我对将显示此内容的页面的内容安全策略(CSP) 进行了更改。具体来说,我将frame-src指令设置为只允许 iframe 内容的某些有效来源。例如:
res.setHeader("Content-Security-Policy", "frame-src https://youtube.com");
请注意,实际的 CSP 会更长。这只是使用 frame-src 指令的一个示例。
我不确定这是否是实现我想要的最安全的方式,但这是我目前能想到的最佳方式。请随时纠正我或补充我的答案。希望有人觉得这很有用。
推荐阅读
- java - 需要有关 java.io.UnixFileSystem.getspace 方法的信息,执行哪个 unix 命令?
- sql - sql server 中两个日期之间的年份以及每个日期在 sql server 中的开始和结束日期
- php - 通过关联数组的键搜索关联数组的数组数值的差异
- python - 在 python 3 中不使用 with 处理文件仍然不安全吗?
- c - C中检测行尾的解释
- docker - 谷歌云运行 | Angular 项目部署为无服务器容器 | 复制失败:没有指定源文件
- javascript - 从html中的输入获取文件路径
- c++ - 如何检查一组值中的一个是否相等?
- python - 根据每个动作的概率创建动作列表
- angular - 使用组件作为对话框引用,但并非总是如此