为 (草案阶段) 清理器 API 的进展欢呼三声! 这是大家都知道的,你不能信任用户输入。 事实上,我曾经参与的每个应用程序都处理过恶意用户试图在不应出现的地方插入和执行恶意代码的情况。
清理用户输入(在页面上再次使用之前,或存储,或在服务器端使用)是 Web 开发人员的工作。 这通常使用我们自己的代码或从外部引入的库来完成。 我们可以编写一个正则表达式来删除任何看起来像 HTML(或类似)的东西,这存在着错误的风险,而且恶意用户可能会找到绕过我们代码的方法。
我们可以让浏览器来做,而不是使用用户空间库或我们自己处理它。
// some function that turns a string into real nodes
const untrusted_input = to_node("<em onclick='alert(1);'>Hello!</em>");
const sanitizer = new Sanitizer();
sanitizer.sanitize(untrusted_input); // <em>Hello!</em>
然后让它随着时间的推移继续成为浏览器的责任。 正如 草案报告 中所说
浏览器非常了解何时要执行代码。 通过教会浏览器如何以安全的方式从任意字符串渲染 HTML,并且以一种更有可能随着浏览器自身的解析器实现的变化而维护和更新的方式进行,我们可以改进用户空间库。
这种事情是 Web 标准的最佳体现。 发现人们不得不做的事情(令人讨厌和/或危险),然后介入使它更安全、更快、更好。
帮帮我:我找不到在浏览器级别清理用户输入的原因。 为了防止恶意输入被保存到数据库中甚至稍后被输出,我们需要在服务器级别进行清理。 这是因为恶意用户不会犹豫查找 API 并直接将恶意输入发布到那里,绕过任何浏览器级别的检查。
这个 API 更适合从数据库中输出到页面上的信息,作为最后一道防线,类似于在验证/清理进入数据库的数据之后。
系统不应该相互信任。 您的客户端应用程序应该假设来自 API 的响应是恶意的,并且已被攻击者(例如中间人攻击)入侵。 始终清理每个系统的输入/输出。
如果我的客户端应用程序从 API 响应(例如无头 CMS 等)接收一些 html,它应该始终在渲染之前对其进行清理。 这方面的首选方法一直是 https://github.com/cure53/DOMPurify。 我想知道这个新规范与之相比如何。
这可以防止 XSS。 是的,您应该在服务器端进行清理,但是某些应用程序不需要存储数据。 例如,一个非持久性聊天。 您可能希望允许用户共享 html,而不会冒 XSS 风险,而无需在服务器上使用中间件进行清理。 例如,WebRTC 是客户端到客户端的,您希望保护接收端免受执行恶意 JS 的影响。
这与大多数数据无关,而是专门针对您想要显示用户提供的 HTML 而不会冒 XSS 攻击风险的情况。
虽然在服务器上从 HTML 中删除所有 JavaScript 似乎是合理的,但是解析 HTML 是一项非平凡的任务,浏览器在处理方式上略有不同。 因此,攻击者可以构造一个 HTML 负载,在 Firefox 中运行 JS,而在 Chrome 或 JSDOM 中则完全安全。
由于您无法预测查看您网站的每个人的浏览器将如何解析任何给定的 HTML,因此最好按原样存储它,然后利用查看者浏览器的功能为该特定浏览器生成安全的 HTML。
这听起来很棒! 很多网站都需要清理用户输入。 完成此操作的代码可能已经重写了数百万次,每次重写都有可能包含错误。 将此作为平台的一部分非常有意义!