【问题标题】:HTML/XSS escape on input vs output输入与输出的 HTML/XSS 转义
【发布时间】:2012-06-30 11:57:01
【问题描述】:

从我所看到的一切看来,在用户输入的内容上转义 html 的惯例(为了防止 XSS)似乎是在呈现内容时进行。大多数模板语言似乎在默认情况下都会这样做,我遇到过像 this stackoverflow answer 这样的事情,他们认为这个逻辑是表示层的工作。

所以我的问题是,为什么会这样?对我来说,在输入(即表单或模型验证)时转义似乎更干净,因此您可以假设数据库中的任何内容都可以安全地显示在页面上,原因如下:

  1. 多种输出格式 - 对于现代 Web 应用程序,您可能会使用服务器端 html 呈现、使用 AJAX/JSON 的 JavaScript Web 应用程序和接收 JSON(可能有也可能没有一些网页视图,可能是 JavaScript 应用程序或服务器渲染的 html)。所以你必须处理到处都是 html 转义。但是输入在保存到数据库之前总是会被实例化为模型(并经过验证),并且您的模型都可以从同一个基类继承。

  2. 你已经必须小心输入以防止代码注入攻击(当然这通常被抽象为 ORM 或 db 游标,但仍然如此),所以为什么不担心 html 在这里转义,这样你就不必担心任何与输出安全相关的事情?

我很想听听为什么 html 在页面渲染上转义是首选的论点

【问题讨论】:

  • 有趣的问题,问错地方了。

标签: model-view-controller xss


【解决方案1】:

最初的误解

不要将输出的卫生与验证混淆。

虽然<script>alert(1);</script> 是一个完全有效的用户名,但在网站上显示之前绝对必须对其进行转义。

是的,有一个“表示逻辑”,它与“领域业务逻辑”无关。并且所述表示逻辑是表示层处理的内容。尤其是 View 实例。在编写良好的 MVC 中,Views 是成熟的对象(与 RoR 试图告诉您的相反),当应用于 Web 上下文时,它会处理多个模板。

关于你的理由

不同的输出格式应该由不同的视图处理。管理 HTML、XML、JSON 和其他格式的规则和限制在每种情况下都不同。

您始终需要存储原始输入(如果您不使用准备好的语句,请对其进行清理以避免注入),因为有人可能需要在某些时候对其进行编辑。

存储原始版本和 xss 安全的“公共”版本是浪费。如果你想存储清理过的输出,因为每次清理它都需要太多资源,那么你已经对错误的树生气了。这是一种情况,当你使用缓存而不是污染数据库时。

【讨论】:

    【解决方案2】:

    除了已经写的内容:

    • 正是因为你有多种输出格式,你不能保证它们都需要 HTML 转义。如果您通过 JSON API 提供数据,您不知道客户端是否需要它用于 HTML 页面或文本输出(例如电子邮件)。为什么要强迫您的客户取消转义“Jack & Jill”以获取“Jack & Jill”?

    • 默认情况下,您正在破坏您的数据。

      • 当有人对“amp”进行关键字搜索时,他们会得到“Jack & Jill”。为什么?因为您损坏了数据。

      • 假设其中一个输入是 URL:http://example.com/?x=1&y=2。您要解析此 URL,并提取 y 参数(如果存在)。这静默失败,因为您的 URL 已损坏为 http://example.com/?x=1&y=2

    • 这只是错误的层级 - 与 HTML 相关的内容不应与原始 HTTP 处理混为一谈。数据库不应存储与一种可能的输出格式相关的内容。

    • XSS 和 SQL 注入并不是唯一的安全问题,您处理的 每个 输出都存在问题 - 例如文件系统(想想像 '.php' 这样的扩展名会导致 Web 服务器执行代码)和 SMTP(想想换行符),以及其他任意数量。认为您可以“处理输入的安全性然后忘记它”会降低安全性。相反,您应该将转义委托给不信任其输入数据的特定后端。

    • 您不应该“到处”进行 HTML 转义。您应该为每个需要它的输出准确地执行 一次 - 就像任何后端的任何转义一样。对于 SQL,您应该 一次 进行 SQL 转义,SMTP 等也是如此。通常,您不会进行 任何 转义 - 您将使用一个库为您处理。

      如果您使用的是合理的框架/库,这并不难。我从来没有在我的网络应用程序中手动应用 SQL/SMTP/HTML 转义,也从来没有 XSS/SQL 注入漏洞。如果您构建网页的方法要求您记住应用转义,或者最终导致漏洞,那么您做错了。

    • 在表单/http 输入级别进行转义并不能确保安全,因为无法保证数据不会从另一条路径进入您的数据库或系统。您必须手动确保系统的所有输入都应用 HTML 转义。

      您可能会说您没有其他输入,但如果您的系统增长了怎么办?回头改变决定通常为时已晚,因为此时您已经拥有大量数据,并且可能与外部接口兼容,例如需要担心的公共 API,它们都希望数据被 HTML 转义。

    • 即使是系统的 Web 输入也不安全,因为您通常会应用另一层编码,例如您可能需要在某个入口点进行 base64 编码的输入。您的自动 HTML 转义将丢失该数据中编码的任何 HTML。因此,您将不得不再次进行 HTML 转义,并记住要这样做,并跟踪你在哪里做过。

    我已经在这里扩展了这些:http://lukeplant.me.uk/blog/posts/why-escape-on-input-is-a-bad-idea/

    【讨论】:

    • 我要添加到输出转义“方面”的另一点是,如果为某些输出向量发现了一些新漏洞,那么输出转义意味着您可以更改显示或输出代码和您的用户此后更安全。如果您有输入转义方案,最低安全的做法是取消转义所有数据存储的内容并使用新的转义重新转义代码。要么建立并永远维护一些 JIT 方案,这相当于以更高的成本逃避输出。
    猜你喜欢
    • 2013-06-15
    • 2010-12-07
    • 2014-12-23
    • 2014-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    相关资源
    最近更新 更多