为啥跨域 JSONP 安全,但跨域 JSON 不安全?

Posted

技术标签:

【中文标题】为啥跨域 JSONP 安全,但跨域 JSON 不安全?【英文标题】:Why is cross-domain JSONP safe, but cross-domainJSON not?为什么跨域 JSONP 安全,但跨域 JSON 不安全? 【发布时间】:2011-10-29 23:48:55 【问题描述】:

我在连接最近了解 JSONP 的一些点时遇到了问题。这是我的理解:

由于同源策略,禁止任何内容(包括 JSON)的跨域 XmlHttpRequest。这可以防止 XSRF。 您可以拥有一个带有返回 JSONP 的 src 的脚本标记 - 在调用 javascript 函数(例如“Foo”)中填充了一些 JSON 您可以在页面上实现一些“foo”的实现,当 JSONP 数据返回时将被调用,并且您可以对函数传递的 JSON 数据执行操作

为什么跨域数据通过 JSONP 可以接收,但如果通过 JSON 就不行?

是否假设 JSON 倾向于允许 XSRF 而 JSONP 不是?如果是这样,除了 JSONP 是某种不会提供启用 XSRF 的数据的事实数据格式之外,还有什么理由吗?为什么选择 JSONP 而不是 XML 上的任意根标签?

提前感谢您的回答,请在无法弄清楚这一点后让我的大脑再次工作。

【问题讨论】:

JSONP 仅与提供 jsonp 文本的服务器一样安全。没有什么说 jsonp 服务器不能发送恶意代码/数据。 jsonp 纯粹用于绕过同源策略。它具有与常规 json 字符串相同的所有风险,以及作为实际 JS 代码的额外好处,而不仅仅是 js 数据。 我应该澄清我的明确问题。如果可以通过使用JSONP跨域检索JSON数据(当我说'安全'时,我的意思是浏览器允许它),为什么通过其他机制跨域检索JSON数据并不同样可以,例如XmlHttpRequest? 现在大多数浏览器都有一个原生 json 实现来编码/解码字符串,这没什么大不了的......但最初 json 支持是通过 eval() 完成的,所以你会正在运行返回的字符串,而不仅仅是处理它。 JSONP 只是一种自愿的 XSS 攻击。我们通过简单地从远程域注入脚本来绕过相同的来源限制。理论上,远程域可以使用此脚本来破解您的所有用户并完全控制您的站点。谨慎使用。 【参考方案1】:

我理解这个问题是关于为什么浏览器认为 JSONP 安全,而不是关于它是否安全(它不安全)。我将逐步解决这个问题。

普通的 AJAX

要执行常规的 AJAX 请求,浏览器会创建一个 XHR 对象,将其指向 URL 并提取数据。 XHR 对象将只信任来自同一域的数据。这是一个硬性限制。在当前的浏览器中无法绕过它(编辑 - 您现在可以使用 CORS)。

解决方案 - 不要使用 XHR

由于 XHR 受制于相同的域策略,我们不能使用 XHR 进行跨域 AJAX。幸运的是,还有其他方法可以访问远程服务器。例如,我们可以将图像标签附加到页面。我们还可以附加一个脚本标签,并给它一个指向远程服务器的 src 属性。例如,我们可以从 CDN 中提取 JQuery 并期望它能够正常工作。

JSONP 的工作原理。

当我们发出 JSONP 请求时,我们的代码会动态地将脚本标记附加到页面。 script 标签有一个指向远程 JSONP API url 的 source 属性,就像您从 CDN 插入脚本一样。

服务器返回的 JSONP 脚本封装在函数调用中。脚本下载后,函数会自动执行。

这就是为什么我们必须告诉 JSONP 我们要包装脚本的回调函数的名称。一旦脚本下载,该函数将被调用。

安全问题

这里有一些相当大的安全问题。您正在下载的脚本可能会控制您的页面并使您的用户面临风险。 JSONP 对您的用户来说并不安全,它只是没有被 Web 浏览器阻止。 JSONP 确实是我们正在利用的浏览器漏洞。谨慎使用。

如果使用得当,JSONP 还是非常棒的。

【讨论】:

【参考方案2】:

我不知道 JSONP 是安全的看法是如何产生的,但请看

因此,JSON-P 被许多人视为不安全和 hacky 跨域 Ajax 的方法,这是有充分理由的。作者必须是 努力只对他们认为的远程 Web 服务进行此类调用 控制或隐含信任,以免使用户受制于 伤害。

该提案中最关键的部分是浏览器供应商必须 开始对接收 JSON-P 的脚本标签强制执行此规则 内容,并在任何内容上抛出错误(或至少停止处理) 不符合标准的 JSON-P 内容。

http://json-p.org/ 的两个引用。

其他包含有关 JSONP/安全性的有用信息的链接:

http://beebole.com/en/blog/general/sandbox-your-cross-domain-jsonp-to-improve-mashup-security/ Cross Domain Limitations With Ajax - JSON JSONP Implications with true REST

所有这些都说明了两件事 - 基本上它不被认为是“安全的”,但有一些关于如何使其“更安全”的想法......尽管大多数想法都依赖于标准化和特定的检查逻辑以内置到浏览器等中。

【讨论】:

啊,让我更清楚一点我所说的“安全”是什么意思。浏览器不允许您执行跨域 XmlHttpRequests,因为浏览器不认为它是“安全的”。但是你可以做跨域的 JSONP 请求,这样你就可以得到跨域的 JSON。什么是 JSON 的“不安全”(我想是为了 XSRF 的目的)对 JSONP 是安全的? 绝对没有 - 根据标准,<script>-elements 没有“同源策略”,这是规避这种“限制”的方法(安全动机) XmlHttpRequest 的。早在 AJAX 发生之前,同样的技术就已经在使用了——否则你将无法在页面中从不同的主机(如 Google)加载 jQuery...

以上是关于为啥跨域 JSONP 安全,但跨域 JSON 不安全?的主要内容,如果未能解决你的问题,请参考以下文章

Ajax跨域问题解决(Ajax JSONP)

jquery ajax使用JSONP解决跨域问题

JSONP跨域

jquery ajax使用JSONP解决跨域问题

jsonp 方式处理跨域前后端代码如何配合?

跨域及JSONP原理