【问题标题】:Is .text() safe or not to sanitize data? [JQuery].text() 是否安全以清理数据? [jQuery]
【发布时间】:2015-06-10 01:47:00
【问题描述】:

我看到其他地方有人问过这个问题:

Escaping HTML strings with jQuery

@travis 标记为正确的答案说 .text() 很好。但是,有些人在评论中(例如@nivcaner 和@lior)提到这种解决方案并不好。我们站在哪里?我可以安全使用它吗?

我正在开发一个 Web 应用程序,用户可以在该应用程序中在其浏览器中创建一个可以通过 JQuery 添加表格、标题和视频的文档。当用户“保存”他的文档时,它的结构被翻译成一个数组,其中数组的所有元素都由“纯”文本组成,没有标签(例如,每个表格单元格都有一个数组元素,其中包含该文本的文本)细胞等)。然后将数组转换为 JSON 格式并发送到服务器,并通过 PHP 以 JSON 格式处理/清理/保存。

之后,其他用户可以访问该文档,这当然会引入潜在的安全漏洞。想法是他们从服务器读取 JSON 数据,然后在客户端通过 javascript/JQuery 重新创建文档。

虽然我非常有信心我的 PHP 代码能够正确地清理 JSON 数据,但我担心恶意用户可能会欺骗其他用户从不受信任的来源读取 JSON 数据的攻击。出于这个原因,我觉得最好在客户端重新创建表等之前验证来自服务器的任何 JSON 数据。假设变量currentCellText 包含要写入表格单元格#mytd 中的(JSON 读取)文本,我可以安全地使用代码$("#mytd").text(currentCellText) 重新创建单元格内容吗?

【问题讨论】:

  • @DanielG。使用 HTTPS,你可以避免这个问题。
  • @DanielG。这取决于您的托管服务。我使用 Heroku,它不会为 HTTPS 收取额外费用,实际上同时支持对同一服务器的 HTTP 和 HTTPS 请求。如果 HTTPS 为您带来额外费用,您可能需要考虑使用其他主机。
  • HTTPS 的计算成本在现代硬件上介于零和无法测量之间。这在 2015 年根本不是问题。与 HTTPS 相比,提供臃肿的非压缩资产对性能的影响更大。
  • @tadman :经过一番思考,我相信 HTTPS 无处不在,可以避免中间人攻击。如果我的 JSON 数据可能受到此类攻击的影响,那么我的服务器提供的所有文件都可能受到影响,包括用于“清理”JSON 的 HTML 和 javascript……HTTPS 是要走的路。
  • 如果您需要保护它,这意味着您至少需要 HTTPS。真的没有办法解决。希望这不会太麻烦。

标签: jquery json sanitization


【解决方案1】:

来自jQuery .text() article

我们需要注意,此方法会根据需要对提供的字符串进行转义,以便在 HTML 中正确呈现。为此,它调用 DOM 方法 .createTextNode(),不会将字符串解释为 HTML。

这意味着数据被存储到一个文本节点,根据规范,它不能将存储的文本呈现为 HTML,因此使用$("#mytd").text(currentCellText) 应该是安全的。

jQuery 实现的 1.x 行支持本文。当您查看 jQuery 1.11.3 的未压缩源代码时,您会发现:

jQuery.fn.extend({
    text: function( value ) {
        return access( this, function( value ) {
            return value === undefined ?
                jQuery.text( this ) :
                this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
        }, null, value, arguments.length );
    },
    ...

相关行是这样的:

this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );

该行的大部分内容只是定位正确的document 来创建文本节点,但作为传入字符串的value 永远不会直接被解释为HTML。

此外,查看 jQuery 2.1.4 的未压缩代码,您会发现该实现使用 .textContent 属性进行赋值,该属性依赖于浏览器实现来对传递的文本进行完全净化,而不是部分:

jQuery.fn.extend({
    text: function( value ) {
        return access( this, function( value ) {
            return value === undefined ?
                jQuery.text( this ) :
                this.empty().each(function() {
                    if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
                        this.textContent = value;
                    }
                });
        }, null, value, arguments.length );
    },
    ...

这段代码的相关部分在这里:

this.empty().each(function() {
    if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
        this.textContent = value;
    }
});

因为这是在将参数传递给 .text() 函数时执行的操作。

【讨论】:

  • 所以这基本上意味着 .text() 转义引号和双引号,这与 Lior 在我上面提到的评论中所说的相反?
  • @DanielG。不,它不会转义引号和双引号,但我已经彻底阅读了该评论,并且根据您的情况的 context,我认为转义引号并不重要,因为您正在解析它作为完整的 HTML,而不是使用模板在 HTML 的特定部分注入字符串。
  • 为什么不会转义引号和双引号?
  • @DanielG。因为没有必要将它们转义以将字符串呈现为文本而不是 HTML。
  • 有道理!你说的我也考虑了一下,我也认为转义引号对于防止这种情况下的代码注入攻击无关紧要。
猜你喜欢
  • 2021-05-10
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
  • 2013-12-19
  • 1970-01-01
  • 2012-10-15
相关资源
最近更新 更多