使用来自不受信任的来源(例如其他用户)的URL参数调用jQuery的$.getJSON()
是否安全?换句话说,使用不受信任的URL调用$.getJSON()
是否安全?我会小心不要相信响应并安全地处理响应,但调用本身是否会带来安全风险?
换句话说,我说的是:
$.getJSON(url_from_user, function(...) { ... handle response safely ...});
或
$.getJSON('http://evil.com/foo.json', function(...) {...});
如果某个不受信任的用户为url_from_user
提供恶意值或某人恶意控制evil.com
网站,是否允许代码注入或XSS?再次假设将返回任何返回的JSON对象。
documentation for getJSON没有说明这种情况是否安全。从逻辑上讲,我希望这个场景是安全的,因为我希望jQuery的实现能够通过XHR下载JSON对象的文本,使用安全的JSON解析器解析这个文本,然后返回JSON对象。
然而,在查看jQuery源代码之后,我对这是否安全存有疑问。浏览the source code for 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()
是否安全?如果在某些情况下它可能不安全,在什么条件下(例如浏览器版本)是安全/不安全的?
答案 0 :(得分:7)
除非您将请求配置为永远不要使用JSONP(在某些情况下jQuery将自动尝试用于某些跨源请求),否则对任何随机外部URL使用$.getJSON()
是不安全的。
如果jQuery切换到JSONP,这将直接从另一个源启用脚本注入页面,因为JSONP正好通过脚本注入工作(为了通过常规Ajax调用来规避相同来源的限制)。
为防止此类误用,您必须阻止使用JSONP,并且必须调查在jQuery中执行此操作的最可靠方法。您也许可以切换到$.ajax()
,在那里您可以指定更多选项来控制事物。
如果这是我的代码,我可能会试图完全跳过这个Ajax调用的jQuery,并且只使用我自己的xmlHttpRequest
对象来绝对保证它只进行纯Ajax调用(没有回退到任何其他运输,如JSONP)。
<强>更新强>
我一直试图找到$.getJSON()
将在jsFiddle上的各种测试场景中发出JSONP请求的情况。我找不到一个。目标站点有一个允许跨源请求的Access-Control-Allow-Origin标头,在这种情况下,jQuery只进行跨源Ajax调用,或者它没有标头,jQuery只是失败了getJSON()
呼叫。因此,看起来需要对特定版本的jQuery进行一些认真的研究,以确定它是否真的被欺骗在某种类型的&#34; auto&#34;中进行JSONP调用。模式,当你没有明确要求一个。
更新2:发现实际漏洞
我发现了一个漏洞。如果发送到$.getJSON()
的URL包含查询参数callback=
,则jQuery将执行JSONP,目标主机可以通过响应注入所需的任何脚本。
这是一个使用可公开访问的Flickr JSONP端点的演示:
http://jsfiddle.net/jfriend00/z6ah9eh2/
这并不是出于意图错误,但它会通过$.getJSON()
执行直接到目标网站的任意Javascript。因此,它肯定容易受到JSONP代码注入的攻击。</ p>
以下是来自$.getJSON()
的jQuery文档的引用:
如果URL包含字符串
"callback=?"
(或类似的,由...定义) 服务器端API),请求被视为JSONP。
并且&#34;被视为JSONP&#34;意味着它将插入脚本标记并请求并从URL中的站点运行脚本 - 因此,如果您使用JSONP访问不受信任的站点,则会打开跨站点脚本漏洞。
JSON背后的一个想法是,它可以使用纯文本解析器进行解析,该解析器严格遵守JSON规范,除了纯JSON之外,还允许或可以通过。如果有人试图将一些Javascript代码隐藏到JSON字符串中,那么任何半正式的JSON解析器都会将JSON拒绝为无效并抛出异常。在一个适当的世界中($.getJSON()
是),JSON不会被Javascript解析器解析,它会被它自己的文本解析器解析,它只接受有效的JSON,而不是其他Javascript结构。
这是JSON解析器的安全可靠实现背后的理念,它被认为$.getJSON()
使用(任何解析器中都可能存在未知的错误,但是已经做了设计以确保安全)。
所以,这个障碍已经过去了。没有任何技巧可以插入到一个JSON中,该JSON使用一个可以导致后门代码注入的不错的JSON解析器进行解析。
现在,另一个障碍取决于您使用JSON本身所做的事情以及您对JSON的处理或使用是否会导致潜在的恶意行为。
例如,如果从JSON中提取字符串属性并将其作为对象上的方法执行而不进行任何检查以查看该字符串是否为预期值,那么您的代码可能会被欺骗执行方法那你不打算。这仍然不会在您的页面中插入代码,但它会执行您不想要的内容。您可以在使用之前通过正确验证数据来避免这种情况。所以,如果你说,你正在安全地使用JSON,那么这应该不是问题。