使用 JSONP 时是否需要考虑任何安全问题?
4 回答
更新:JSONP 是执行跨域请求的常见技巧。现代浏览器现在有跨域资源共享,IE8+ 有类似的 XDomainRequest。有关详细信息,请参阅http://enable-cors.org/。
JSONP 只是一个脚本包含,允许您使用回调。但是,您应该注意Cross-site request forgery (CSRF)。
只要您控制脚本和服务器,JSONP 就不再比脚本包含不安全。除非您有一个 JSONP 服务将敏感数据返回给登录用户。恶意站点可以向服务发送请求(希望用户登录到您的站点),然后检索数据。该服务可以检查请求的引用者,但可以使用 flash 来欺骗引用者(感谢 Chris Moschini)。
想象一下这个情景: - 用户登录到他的网上银行账户。在用户浏览器中存储会话 cookie。该站点有一个 jsonp 服务,其中包含有关用户及其帐户的敏感信息。- 其他站点不会知道用户已登录,但他们可以大胆猜测并尝试访问 jsonp 服务。由于用户有一个会话 cookie,浏览器会得到响应,并且没有什么可以阻止站点进行 ajax 发布以将敏感数据保存在其服务器上。
2012 年 6 月 28 日更新:如果您想防止 CSRF 攻击,您应该阅读安全专家的这篇深入博客文章:http ://erlend.oftedal.no/blog/?blogid=130
是的,您需要小心,但是当与受信任的服务一起使用时,它是相对安全的。
据我了解,以下是 JSONP 安全问题的摘要:
从消费者的角度来看:
- 您必须信任提供程序不会返回恶意 JavaScript,而不是返回您指定的 JSONP 回调中包装的预期 JSON。
- 任何第三方 JavaScript 嵌入式附加组件也是如此,例如 Google Analytics。
- 它与 XSS 攻击的唯一相似之处在于它允许第 3 方在您的应用程序中执行任意 JavaScript,但是,您必须首先通过发出请求来选择信任第 3 方。
从供应商的角度来看:
- 即使请求中存在客户的 cookie,您也不得假设消费者是您控制的网页。根据授权 URL 的白名单检查 Referer 标头,和/或不要依赖基于 cookie 的身份验证。
- 类似于 CSRF / 混淆代理攻击。
双方都有安全问题。最严重的是包括 JSONP 在内的网站。
如果您包含来自另一个域(您无法控制)的 a,则该域可以随时更改脚本。他们可以使 javascript 在您的网页上下文中执行任何您自己的 javascript 可以执行的操作。如果您使用 JSONP,则无法解决此问题。您应该研究使用 iframe 的跨域通信,这最好由优秀的 EasyDXM 库完成。
如果您提供处理 JSONP 的 Web 服务,则必须防止跨站点请求伪造 (CSRF)。这是您的网络服务向登录用户返回敏感信息的地方。如果用户已登录您的站点,则任何其他站点都可以向 JSONP 服务生成 GET 请求,并且您的域的 cookie 会随请求一起提交——本质上是对登录用户进行身份验证——除了现在,远程域获得响应并能够读取敏感数据!
防止 CSRF 的最佳方法是生成一个随机数(一个难以猜测的随机生成的数字)并将其存储在会话中。在您网页上的所有表单中输出此 nonce,并将其包含在您网页上的所有 JSONP 请求中。在服务器上,确保请求中的 nonce 存在且正确(无论是 GET、POST 等)。其他域将无法猜测此 nonce,因此无法获取敏感信息,尽管有 cookie被发送。
最后,还有另一种安全问题:JSONP 根本不支持浏览器中的用户身份验证,而 OAuth 则可以。当然,您可以让服务器获取某种访问令牌(例如使用 OAuth)并使用它。但是,如果您想完全在浏览器中进行身份验证,则必须使用 iFrame 进行跨域通信。我认为这就是 OAuth 2.0 的做法。以下是您的设置方式:您网站上托管的页面可以完全访问您的服务器。拥有一个加载 EasyDXM 并使用它为您的网站设置隐藏 iframe 的 javascript 库,并使用它与之交谈。
JSONP 绝对不安全,因为它只是将跨域的任何东西作为 JavaScript 运行。
解决方案!解决方案!
创建一个 iframe,最好是一个沙盒,并在那里加载 JSONP。捕获结果并通过window.postMessage
是的,像往常一样,有人首先想到了这个想法:)
博客文章不再存在,但我将链接保留在此处以获取信用:
http
://beebole.com/blog/general/sandbox-your-cross-domain-jsonp-to-improve-mashup-security/
编辑:回程机链接
它使用 window.name hack 进行 iframe 通信,但那是针对 IE6 和 7 的。