JSONP是否安全使用?

70

在使用JSONP时,是否存在应考虑的安全问题?


该网站确实是一个安全的网站。我只想知道我的服务器存储的cookie是否存在任何安全问题。 - dits59
下面的链接由naugtur提供了一个不错的解决方案,并深入解释了它是如何被破解以及解决方案是如何工作的。请务必查看。 - minghua
1
与修复问题相关的问题:是否可能进行安全的JSONP请求? - Bergi
提交的任何数据都会出现在GET请求的查询参数中,因此可能被记录等,这是一个问题吗? - WW.
4个回答

69

更新:JSONP是进行跨域请求的常见技巧。现代浏览器已经支持跨域资源共享(CORS),而IE8+则有类似的XDomainRequest功能。有关更多信息,请参见http://enable-cors.org/

JSONP只是一个包含回调函数的脚本引用。但您应该注意跨站点请求伪造(CSRF)

只要您控制脚本和服务器,JSONP并不比脚本引用更不安全。除非您的JSONP服务向已登录的用户返回敏感数据。恶意站点可以发送请求到该服务(希望用户在您的站点上已登录),并检索数据。服务可以检查请求的引用者,但使用Flash可以欺骗引用者(感谢Chris Moschini)。

想象一下这种情况: - 用户登录其互联网银行帐户,将会话cookie存储在用户的浏览器中。此站点具有有关用户及其帐户的敏感信息的jsonp服务。 - 其他站点不知道用户是否已登录,但他们可以猜测并尝试访问jsonp服务。由于用户具有会话cookie,浏览器将收到响应,没有任何东西可以阻止该站点发起ajax post以将敏感数据保存在其服务器上。

2012年6月28日更新:如果您想保护免受CSRF攻击,您应该阅读这篇安全专家的深度博客文章:http://erlend.oftedal.no/blog/?blogid=130


2
别处已经指出HTTP_REFERER可以被Flash欺骗,因此服务器通过jsonp提供的任何敏感数据都是容易受到攻击的。 - Chris Moschini
这只是风险的一面。naugtur提供的链接展示了风险的另一面,并提供了更好的解决方案。 - minghua

22

是的,你需要小心谨慎,但如果正确使用可信服务,它相对安全。

以下是我所理解的JSONP的安全问题摘要:

从消费者的角度来看:

  • 你必须信任提供者不会返回恶意JavaScript而不是你指定的JSONP回调中包装的预期JSON。
  • 同样也适用于任何第三方JavaScript嵌入式插件,例如Google Analytics。
  • 它只类似于XSS攻击,因为它允许第三方在你的应用程序中执行任意JavaScript,但是你必须首先选择信任该第三方,才能发起请求。

从提供者的角度来看:

  • 你不能假设即使客户端的cookie存在于请求中,消费者也是你控制下的网页。可以通过将Referer头与授权URL的白名单进行比较,和/或不依赖基于cookie的身份验证来解决这个问题。
  • 类似于CSRF / confused deputy攻击。

12

双方都存在安全问题,其中最严重的是包括JSONP的网站。

如果您在网站中包含来自另一个域(您无法控制的域)的脚本,则该域随时可以更改脚本。它们可以让javascript在您网页的上下文中执行任何操作,就像您自己的javascript一样。如果您使用JSONP,则无法避免这种情况。您应该研究使用iframes进行跨域通信,最好使用优秀的EasyDXM库实现。

如果您提供处理JSONP的Web服务,则必须防止跨站点请求伪造(CSRF)。这是您的Web服务向已登录用户返回敏感信息的情况。如果某个用户已登录到您的网站,任何其他站点都可以生成GET请求到JSONP服务,并提交您域的cookie - 从本质上讲,对已登录用户进行身份验证 - 但现在,远程域获取了响应并能够读取敏感数据!

防范CSRF的最佳方法是生成一个nonce(一个难以猜测的随机数),并将其存储在会话中。在您的所有表单中输出此nonce,并在您的所有页面上的JSONP请求中包含它。在服务器上,确保请求中存在并正确的nonce(无论是GET、POST等)。其他域将无法猜测此nonce,因此即使cookie被发送,也无法获取敏感信息。

最后,还存在另一种安全问题:JSONP在浏览器中不支持用户身份验证,这种身份验证可以使用OAuth实现。当然,您可以让服务器获取某种访问令牌(例如OAuth),然后使用它。但是,如果您想完全在浏览器中进行身份验证,则必须使用iframe进行跨域通信。我认为这就是OAuth 2.0的实现方式。以下是设置方式:托管在您网站上的页面可以完全访问您的服务器。创建一个javascript库,加载EasyDXM并使用它设置到您网站的隐藏iframe,并使用该iframe进行通信。


5

JSONP绝对不安全,因为它会将跨域获取的任何内容作为JavaScript直接运行。

解决方案!解决方案!

创建一个iframe,最好是使用sandbox沙盒模式,并在其中加载JSONP。然后通过window.postMessage捕获结果并将其传递回来。

是的,像往常一样,有人先想到了这个主意 :)

博客文章已经不存在了,但我在这里保留链接以便致谢: http://beebole.com/blog/general/sandbox-your-cross-domain-jsonp-to-improve-mashup-security/
编辑: wayback machine 链接

它使用window.name hack实现iframe通信,但那仅适用于IE6和7。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接