使用getJSON()可以安全地调用不受信任的URL吗? [英] Is getJSON() safe to call on untrusted URL?

查看:100
本文介绍了使用getJSON()可以安全地调用不受信任的URL吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用来自不受信任来源(例如另一个用户)的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对象都将得到安全处理.


我已经完成的更多详细信息和研究

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

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

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

解决方案

除非您将请求配置为从不使用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,才能弄清楚在您未明确要求使用jQuery的情况下,是否可以在某种自动"模式下欺骗它进行JSONP调用. /p>

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

我发现了一个漏洞.如果发送到$.getJSON()的URL包含查询参数callback=,则jQuery将执行JSONP,并且目标主机可以在响应中注入所需的任何脚本.

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

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

这没有任何恶意,但是它确实执行了通过$.getJSON()到达目标站点的任意Javascript.因此,它绝对容易受到通过JSONP注入代码的攻击.<​​/p>

这是jQuery文档中对$.getJSON()的引用:

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

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


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

这是一个安全可靠的JSON解析器实现的思想,据信$.getJSON()会使用JSON解析器(在任何解析器中始终存在未知的错误,但已经进行了一些工作以将其设计为安全).

因此,这个障碍已经过去了.没有技巧可以插入到使用体面的JSON解析器解析的JSON片段中,这会导致后门代码注入.


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

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

Is it safe to call jQuery's $.getJSON() with a URL argument that came from an untrusted source, such as another user? In other words, is it safe to call $.getJSON() with an untrusted URL? I will be careful not to trust the response and to handle the response safely, but does the call itself pose a security risk?

In other words, I'm talking about something like:

$.getJSON(url_from_user, function(...) { ... handle response safely ...});

or

$.getJSON('http://evil.com/foo.json', function(...) {...});

Could this allow code injection or XSS if some untrusted user provides a malicious value for url_from_user or if someone malicious controls the evil.com site? Again, assume that any JSON object returned will be treated safely.


More details and research I've done

The documentation for getJSON doesn't say anything either way about whether this scenario is secure. Logically, I would expect this scenario to be safe, as I would expect jQuery's implementation to download the text of the JSON object via XHR, parse this text using a safe JSON parser, and then return the JSON object.

However, after looking at the jQuery source code, I have some doubts about whether this is safe. Browsing through the source code for jQuery, it looks like this scenario might potentially allow XSS. The code for getJSON() is a bit elaborate (see src/ajax.js), but it seems to select a "transport" and then use it to send the AJAX request. I see that src/ajax/script.js registers a transport called the "script tag hack transport". This transport works roughly as follows: it adds a script tag to the document, e.g., <script src="http://evil.com/foo.json">, and registers an onload handler that runs when the downloaded script has executed. In other words, the "script tag hack transport" is fundamentally insecure if the site is controlled by an attacker: it is including attacker-controlled script into the document and executing it. Besides the script tag hack transport, there's also a XHR transport that uses the browser's XMLHttpRequest() API. I am having a hard time following the twisty logic that determines under which conditions the "script tag hack" transport will be used.

So, coming back to my original question, is it safe to call $.getJSON() with a user-provided URL? If it is potentially unsafe under some conditions, under what conditions (e.g., browser versions) is it safe/unsafe?

解决方案

Unless you configure your request to NEVER use JSONP (which jQuery will automatically try to use for some cross origin requests in some circumstances), it is not safe to use $.getJSON() against any random foreign URL.

If jQuery switches to JSONP, that would directly enable script injection into your page from the other origin since JSONP works precisely by script injection (in order to circumvent same-origin limitations with regular Ajax calls).

To prevent this type of mis-use, you will have to prevent any use of JSONP and would have to investigate the surest way to do that in jQuery. You could perhaps switch to $.ajax() where you can specify a lot more options to control things.

If this were my code, I might be tempted to even skip jQuery entirely for this one Ajax call and just use my own xmlHttpRequest object to absolutely guarantee that it was only doing a pure Ajax call (no fallback to any other transport like JSONP).

Update:

I've been trying to find a circumstance where $.getJSON() will issue a JSONP request in various test scenarios on a jsFiddle. I have not been able to find one. Either the target site has an Access-Control-Allow-Origin header that allows cross origin requests in which case jQuery just does a cross origin Ajax call or it doesn't have the header and jQuery just fails the getJSON() call. So, it looks like it would take some serious study of a specific version of jQuery to figure out if it could actually be tricked into doing a JSONP call in some sort of "auto" mode when you didn't explicitly ask for one.

Update 2: Found an actual vulnerability

I found a vulnerability. If the URL sent to $.getJSON() contains a query parameter callback=, then jQuery will execute JSONP and the target host can inject whatever script it wants with the response.

Here's a demo using a publicly accessible Flickr JSONP endpoint:

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

This doesn't doing anything with mal-intentions, but it does execute arbitrary Javascript that is up to the target site via $.getJSON(). So, it is definitely vulnerable to code injection via JSONP.

Here's a quote from the jQuery docs for $.getJSON():

If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead.

And, "treated as JSONP" means it's going to insert a script tag and request and run a script from the site in the URL - thus opening a cross site scripting vulnerability if you access an untrusted site with JSONP.


One of the ideas behind JSON is that it can be parsed with a plain text parser that strictly adheres to the JSON specification and NOTHING besides pure JSON is allowed or can get through. If anyone tries to sneak some Javascript code into a JSON string, any semi-decent JSON parser will just reject the JSON as invalid and throw an exception. In a proper world (which $.getJSON() is), JSON is not parsed with the Javascript parser, it is parsed with it's own text parser that strictly accepts only valid JSON, not other Javascript constructs.

That is the idea behind a safe and secure implementation of a JSON parser which it is believed that $.getJSON() uses (there could always be unknown bugs in any parser, but work has been done to design it to be safe).

So, this hurdle has been passed. There are no tricks that can be inserted into a piece of JSON that is parsed with a decent JSON parser that will cause backdoor code injection.


Now, another hurdle depends upon what you are doing with the JSON itself and whether your handling or use of the JSON enables potential mal-behavior or not.

For example, if you pull a string property from the JSON and execute it as a method on an object without any checking to see if that string is an expected value, then your code might be able to be tricked into executing a method that you did not intend. This still doesn't insert code into your page, but it does execute something you didn't intend. You can avoid that by proper validation of the data before you use it. So, if as you say, you are using the JSON safely, then this should not be an issue.

这篇关于使用getJSON()可以安全地调用不受信任的URL吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆