【发布时间】:2012-05-04 14:38:52
【问题描述】:
我看不出 JSONP 中的回调函数与 AJAX 中的成功回调函数有何不同。
鉴于 #1,我看不出它从根本上更安全。
那么唯一的区别是与 AJAX 的人为同域约束吗?
为什么 AJAX 不能只允许跨域请求;如果这会导致安全漏洞,那么攻击不会只是 XSS 一个 JSONP 请求吗?
困惑, 最大
【问题讨论】:
标签: javascript jsonp
我看不出 JSONP 中的回调函数与 AJAX 中的成功回调函数有何不同。
鉴于 #1,我看不出它从根本上更安全。
那么唯一的区别是与 AJAX 的人为同域约束吗?
为什么 AJAX 不能只允许跨域请求;如果这会导致安全漏洞,那么攻击不会只是 XSS 一个 JSONP 请求吗?
困惑, 最大
【问题讨论】:
标签: javascript jsonp
ajax 调用是从客户端直接到服务器的实际 HTTP 请求。 Ajax 调用可以是同步的(阻塞直到它们完成)或异步的。由于同源安全保护,ajax 调用只能对来自网页的同一服务器进行,除非目标服务器明确允许使用 CORS 的跨源请求。
JSONP 调用是一个有趣的 hack,带有 <script> 标签,允许跨域通信。在 JSONP 调用中,客户端创建一个脚本标记并在其上放置一个带有 callback=xxxx 查询参数的 URL。该脚本请求(通过脚本标签插入)由浏览器发送到外部服务器。浏览器只是认为它正在请求一些 javascript 代码。然后,服务器为此调用创建一些特殊的 javascript,并且在该 javascript 返回时将由浏览器执行,服务器对 callback=xxxx 查询参数中命名的函数进行函数调用。通过定义变量或将数据传递给该函数,服务器可以将数据传回给客户端。对于 JSONP,客户端和服务器都必须在 JSONP 调用如何工作以及如何定义数据方面进行合作。客户端无法对未明确支持 JSONP 的服务器进行 JSONP 调用,因为必须由服务器构建正确类型的 JSONP 响应,否则它将无法工作。
因此,这两种通信方式的工作方式完全不同。只有 ajax 调用可以是同步的。由于<script> 标签插入的性质,JSONP 调用始终是异步的。
在 Ajax 调用中,响应在 ajax 事件处理程序中返回。
在 JSONP 调用中,当返回的 Javascript 调用您的函数时,就会产生响应。
在某些方面,JSONP 是一个绕过跨域安全机制的安全漏洞。但是,您只能调用明确选择支持类似 JSONP 机制的服务器,因此如果服务器不希望您能够调用它跨域,它可以通过不支持 JSONP 来阻止它。您不能对这些其他服务器进行定期 ajax 调用。
浏览器制造商无法真正关闭这个漏洞,因为如果他们这样做了,无数的网页会破坏已经使用 JSONP 或从其他域加载脚本的网页。例如,Web 上使用 Google 或 Microsoft CDN 之外的 jQuery 的每个页面都会崩溃,因为不允许浏览器从跨域域下载 javascript。
JSONP 主要是作为一种解决方法而发明的,以便能够发出跨域请求。但是,由于 JSONP 需要明确的服务器支持才能工作,所以这并不是真正的安全问题,因为只能对明确决定允许这种类型的跨源调用的服务器进行 JSONP 调用。 JSONP 现在的使用比以前少得多,因为 CORS 被发明为一种更优雅的方式来控制/允许它。 CORS 代表Cross Origin Resource Sharing,它为目标服务器提供了一种方法来告诉 Web 浏览器究竟允许什么类型的跨源请求,甚至告诉它允许哪些网页域发出此类请求。它具有比 JSONP 更精细的控制功能,并且所有现代浏览器现在都支持 CORS。
这是一个跨域调用如何导致问题的示例。如果您可以从任何其他网页加载任意网页或进行任意 ajax 调用,那么想象您已经在其他浏览器窗口中登录到 Yahoo 上的 webmail 界面。这意味着您的 cookie 设置为允许来自浏览器的请求从雅虎获取数据。如果允许其他网页中的 javascript 向 Yahoo 发出 webmail 请求(这将自动附加您的 cookie),则它可以获取您的所有 webmail 数据并将其发送回它自己的站点。一个网站可以窃取任何其他网站的所有登录数据。所有的网络安全都会被破坏。
但是,按照我们今天的方式,只要 Yahoo 不支持使用相同 Web cookie 的 JSONP 接口,它就不会受到未经授权的 JSONP 请求。
以下是关于跨域 ajax 的危险以及为什么必须防止它的其他一些很好的文章:
Why the cross-domain Ajax is a security concern?
Why Cross-Domain AJAX call is not allowed?
Why are cross-domain AJAX requests labelled as a "security risk"?
【讨论】:
根本的区别在于,出于某种原因,加载位于其他域的 javascript 文件(通过 script 标签)是完全可以的,但默认情况下加载其他跨域资源是不行的。
我同意你的看法,因为这种划分似乎相当武断。在jQuery 中,当您执行 JSONP 调用时,实际上是在创建脚本标记、加载资源,然后 jQuery 库通过调用该 JSONP 结果中定义的函数来执行您的脚本。
在我看来,我想不出通过允许跨域 AJAX 引入的额外攻击向量,通过允许跨域脚本加载,它还没有扩大,这是到处使用的常见做法(googleCDN 的 jQuery,广告脚本,谷歌分析,以及无数其他)。
In addition, many legacy cross-domain operations predating JavaScript are not subjected to same-origin checks; one such example is the ability to include scripts across domains, or submit POST forms.
【讨论】:
JSONP 的回调不是真正的回调。相反,JSONP 通过 脚本注入 工作。例如,如果您想进行 JSONP 调用,则将此脚本元素插入 DOM:
<script src="http://example.com/ajaxendpoint?jsonp=parseResponse"></script>
服务器的响应是这样的:
parseResponse({"json":"value"});
它将在窗口的全局范围内评估。所以本质上 JSONP 就像一个远程的exec(),服务器被告知要创建什么字符串来执行。
这与 Ajax非常不同:使用 JSONP,响应是在脚本的全局范围内评估;使用 XMLHttpRequest,响应作为字符串接收,而不是评估。 (另外,JSONP 只能与 GET 一起使用,而 AJAX 允许任何 http 方法。)
因此对于您的第二个问题,“我看不出它从根本上如何更安全。”嗯,你是对的,JSONP 实际上非常不安全。服务器可以返回它想要的任何脚本,然后为您的浏览器做任何它想做的事情!
跨域请求是不安全的,因为它们可用于将有关当前页面的信息透露给另一个域上的页面。
你是对的,任何 XSS 攻击都可以使用 JSONP。 CORS 的目的不是防止 XSS(如果您的页面上运行了不受信任的脚本,那么您无论如何都会被淹没)。
【讨论】: