【问题标题】:How safe is client-side HTML Sanitization?客户端 HTML 清理的安全性如何?
【发布时间】:2014-07-13 09:36:30
【问题描述】:

我最近一直在关注 Pagedown.js,因为它具有在我的页面上使用 mark-down 而不是丑陋的只读文本区域的魅力。

我非常谨慎,因为它似乎很容易欺骗经过消毒的转换器。我已经看到一些关于 Angular.js 和它的 html 绑定的讨论,并且在 Knockout.js 3.0 发布时也听说过之前 html 绑定存在不安全性。

似乎有人需要做的就是禁用 Pagedown.js 中的消毒剂,例如 -

var safeConverter = new Markdown.Converter();
// safeConverter is open to script injection

safeConverter = Markdown.getSanitizingConverter();
// safeConverter is now safe

// Override the getSanitizingConverter pseudo-code
Markdown.getSanitizingConverter = function () {
    return Markdown.Converter;
};

他们可以打开一个站点进行脚本注入。这不是真的吗?

编辑

那么为什么像这样的库会打包一个消毒剂来使用客户端呢?当然他们说不要渲染未经处理的 html,但下一行说使用 Markdown.Sanitizer..

Angular 为何不使用 sanitizer 服务对其开放,或者这也只是一场闹剧?

【问题讨论】:

  • 完全正确。 没有什么客户端是安全的。
  • 似乎有更多的回答者回答,好像这个问题是关于客户端验证的。清理是完全不同的事情(实际上它发生在频谱的完全相反的一面:(客户端)验证发生在用户发送数据之前,(客户端)清理发生在用户从服务器接收数据之后)。 Sanitizaton确实让您的应用更安全,但只能与其他措施/实践结合使用。
  • 这是朝着正确方向迈出的非常重要的一步,绝对应该成为您应用程序的一部分。但是,它并不能神奇地解决您的所有问题。它是一个有用的工具,应该相应地使用和处理。

标签: javascript html angularjs knockout.js javascript-injection


【解决方案1】:

您无法清理客户端。任何人都可以随时关闭 JavaScript 或更改值并将它们提交到您的服务器。

服务器需要仔细检查。在我看来,客户端实际上只是一个可用性功能。所以他们在打字时就知道自己是错的还是正确的。

回应编辑:

其中大多数是方便或提供功能。例如,unobtrusive validation 如果输入无效数字,我的文本框将变为红色。太好了,我不需要发帖检查然后更改文本框边框blablablabla...

但是当他们发帖时,我仍然需要验证他们的数据。我通常将它保存在一个可以跨应用程序(Web、Web 服务、移动应用程序、胖客户端等)共享的核心库中

可用性验证因平台而异。但核心是,在任何应用程序信任数据之前,它必须在其信任屏障内对其进行检查。没有人可以在服务器上更改我if 后面的值,但是任何人都可以在浏览器中更改值而不会触发我的 JS。

【讨论】:

  • 是的,您可以在客户端进行消毒(这也是一个好主意)。消毒 !== 验证
  • Admiral Adama 我很欣赏你的回答,但我觉得这与我对消毒剂的误解相同,我相信 ExpertSystem 的回答更好地解决了这个问题并提供了更好的参考来支持它 - 如果如果您不同意,请随时告诉我,我们可以讨论!
  • 我同意,几天前我在阅读他的帖子时投票支持他。这是一个很棒的帖子。我抓住了你使用的“安全”字眼。问题是,虽然它可以帮助保护最终用户,但它并不能取代清理和安全服务器端。我仍然建议这不是防止 XSS 的安全方法,依靠这个库来工作客户端是不安全的。但这很有帮助:)。感谢@PWKad 的说明
  • @ExpertSystem 如果关闭了 Javascript,您也不能在客户端进行清理。
  • @RobertMallow:你也不需要。
【解决方案2】:

Pagedown 可以在服务器上运行,也可以在客户端上运行。

为了在客户端清理 html,清理输出而不是输入更有意义。您不会在向服务器发送数据之前进行清理,但可以在从服务器接收数据之后进行清理。

想象一下在客户端上调用 Web 服务并从第三方服务获取数据。它可以在渲染之前通过客户端上的消毒剂。用户可以在自己的计算机上禁用清理功能,但这只会伤害自己。

除了安全原因之外,它也很有用,只是为了防止用户输入意外修改周围页面的格式。例如在输入带有实时预览的 html 帖子时(如在 StackOverflow 上)。

【讨论】:

    【解决方案3】:

    一点也不安全。

    应该使用客户端卫生/验证有几个原因:

    • 更轻松、更快捷地告诉非恶意用户他做错了什么
    • 减少非恶意用户与您的服务器通信的次数(以防出现错误)

    您验证的所有内容都可以更改,因为客户端不受您控制。诸如开发控制台、fiddler、wireshark 之类的东西基本上可以让您以任何您想要的方式操作数据。

    所以只有服务器负责真正的卫生/验证。

    【讨论】:

    • 这个问题不是关于验证的;这是关于消毒。
    • @ExpertSystem 你能解释一下这个内容有什么不同吗?验证 - 判断数据格式是否正确(是/否)。卫生 - 将格式不正确的数据转换为正确格式。所以对两者的问题 - NO 是不安全的,因为两者都可以被篡改。如果唯一的问题是我的文本中没有卫生一词 - 它很容易修复。
    • 不,这不是“措辞”的问题。这是一个完全不同的概念,发生在完全不同的地点/时间点。你看过我的回答了吗?
    • @ExpertSystem 是的,我读过。它也比我的长得多,但答案是相似的——它不安全,只是为了方便和更好的用户体验。他的问题 - “它安全吗”,所以我基本上可以依靠这种消毒剂并假设它是防弹的。我的回答是——不,你不能也不应该。它可以被篡改。看不出我哪里错了。是的,我没有解释 sanitizer 如何在 Angular 中工作,但我不需要这样做
    • 我认为您不了解消毒剂的用途。您提到的同时适用于清理和验证的原因适用于前者。当然,它不会使您的应用程序防弹(没有什么可以做到这一点),但它确实使它更安全(在几个方面)。
    【解决方案4】:

    我相信对于这种“消毒剂”的目的和性质存在一些误解。

    清理程序(例如 Angular 的 ngSanitize)的目的不是来防止“坏”数据被发送到服务器端。恰恰相反:消毒剂可以保护非恶意用户免受恶意数据的侵害(可能是服务器端存在安全漏洞的结果(是的,没有完美的设置)或从其他来源(您无法控制的来源)获取)。

    当然,作为客户端功能,可以绕过 sanitizer,但是(因为 sanitizer 是为了保护用户(而不是服务器))绕过它只会使绕过器不受保护(你不能做任何事,你也不应该在意——这是他们的选择)。

    此外,清理程序(可以)具有另一个(可能更重要)作用:清理程序是一种工具,可帮助开发人员更好地组织代码,以便更容易测试某些类型的漏洞(例如 XSS 攻击) ) 甚至有助于针对此类安全漏洞进行实际代码审计。

    在我看来,Angular docs 很好地总结了这个概念:

    严格上下文转义 (SCE) 是一种模式,其中 AngularJS 要求在某些上下文中进行绑定以生成一个标记为可安全用于该上下文的值。
    [...]
    SCE 以以下方式协助编写代码:(a)默认安全和 (b)审核安全漏洞,例如 XSS、点击劫持等。a容易得多

    [...]
    在更现实的示例中,可以通过绑定呈现用户 cmets、博客文章等。 (HTML 只是呈现用户控制的输入会产生安全漏洞的上下文的一个示例。)

    对于 HTML,您可以在客户端或服务器端使用库来清理不安全的 HTML,然后再绑定到值并将其呈现在文档中。

    您将如何确保使用这些类型绑定的每个地方都绑定到一个已被您的库清理过的值(或返回以供您的服务器安全呈现?)如何确保您没有意外 删除清理了值的行,或者重命名了一些属性/字段并且忘记将绑定更新为清理后的值?

    为了安全起见,您需要确保禁止任何此类绑定,除非您可以确定某些内容明确表明在该上下文中使用绑定值是安全的。然后,您可以审核您的代码(一个简单的 grep 即可),以确保仅对那些您可以轻松判断为安全的值执行此操作 - 因为它们是从您的服务器接收的,并由您的库进行了清理等。您可以组织您的代码库以帮助解决此问题 - 或许只允许特定目录中的文件执行此操作。确保由该代码公开的内部 API 不会将任意值标记为安全然后成为更易于管理的任务

    注 1: 重点是我的。
    注 2: 很抱歉引述冗长,但我认为这是非常重要的(如非常敏感)物质和一个经常被误解的物质。

    【讨论】:

    • 我知道另一个答案的投票率更高,但我相信这只是因为它的回答速度有多快 - 我相信您的答案更好地解决了客户端消毒剂的目的以及它们如何保护服务器/用户以及如果绕过它们,暴露的风险是什么。
    猜你喜欢
    • 2019-05-05
    • 1970-01-01
    • 2010-09-22
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多