views:

160

answers:

2

In our web application we have run into the situation where we need to do a cross-domain AJAX calls from one domain we fully control to another domain we fully control. I've been surfing around for the best solution and the two that come to mind are a local file proxy (local file using php::fopen) or jquery/JSONP.

When I look up online I see people routinely talk about how it is dangerous to use JSONP because someone could inject malicious data with it. The dilemma is that most of the arguments against it do not seem to hold much water so I'm coming here to ask the Stack for clarification.

What are the specific vectors of attack which would be opened up by cross domain JSONP?

From my understanding the only vector for JSONP is the exact same vector which is opened up by including a <script> tag on your site whose src is to any site that is not controlled by you: That they could turn malicious and start farming user sessions/cookies/data. If that is true, then it would seem that it is not the protocol (JSONP) that is the concern, but rather the source that the data is gathered from. Because whether it was a server-side proxy, a <script> tag, or ajax/JSONP the risk is that I'm putting someone elses content on my page, and they could start farming user sessions if they felt obliged (in a way that's exactly what Google analytics does by way of a script tag).

Many vectors that I hear online hinge upon improper validation of user submitted forms and data. In example, JSONP is used to pull some file, which puts data in a form, and then the form is submitted for database insertion. If the data from that form is trusted, because it's from believed-to-be-secure source (JSONP data), and put in without validation, then again it's not the JSONP at fault, but rather improperly validated user input. A user could make the exact same modifications to that form using Firebug, but last I checked no one is calling Firebug a security vector.

The last element is the notion that with the server-side proxy there is a greater ability to filter the results prior to passing it to the client. Yet, whether it is PHP, or Javascript I could filter the results to remove things like , onclick or iframe. Sure, someone client side could alter my javascript function to remove the filtering, but the filtering would only affect their specific client experience, and would not be altered for other users, thus preventing a permanent multi-client XSS attack. Obviously, there are some benefits to the server side proxy because it would make things like logging potential XSS attacks easier, but in terms of preventing the attack itself both PHP and Javascript seem to have adequate utilities. In some ways, it would seem JSONP is actually more secure than a simple <script> tag because at least with JSONP the result passes through a function which means it somewhat filtered, rather than just blanket trust, as occurs with <script>.

Is there some risk that I am missing or overlooking? If I understand the problem correctly, then there is no security risk for in using JSONP to include contents of a file we trust from a source we trust. Is that an accurate assessment?

SOLUTION

  1. If both ends are trusted, there is no danger in JSONP (it's basically just a <script> tag).

  2. Both Script/JSONP hold the same security vulnerabilities because they are automatically executed, rather than simply transmitting as data. Using a server-side proxy means that the cross-domain return is passed as data and can be filtered for malicious content. If the cross-domain is fully trusted, then JSONP/SCRIPT is safe, if there is any suspicion of risk then pass it through a filter proxy.

+1  A: 

When you control both ends of the request, most of the traditional security worries about JSONP aren't an issue.

One additional problem that you'll encounter is that some users block third-party scripts as a security measure. That will block your JSONP requests as well. The server-side proxy approach does not have that issue.

Dave Ward
+2  A: 

There is a BIG difference between server-side-proxy and <script>/JSONP. In the first case, you download data, in the latter you download and automatically execute code

When you build a server-side-proxy, the javascript code can use XmlHttpRequest to download data. This data will not execute automatically; you have to explicitly do something stupid, like eval(), to get it to execute. Even if the data format is JSON and the other server has been compromised and your own server-side-proxy doesn't catch the compromise, you still have a line of defense available your client code. You can, for example, parse the JSON using a safe JSON parser, and reject malicious script.

But when you use JSONP or a <script> tag, you are directly including someone else's code. Because its code (and not data), the browser automatically executes it, without giving you a chance to inspect or modify it.

To summarize, server-side-proxy gives you two additional lines of defence -

  1. Ability to inspect data on server for malicious content
  2. Ability to inspect data in javascript prior to execution, if at all you need to execute it.
sri
You mentioned two benefits for ss-proxy, but can't I do both of those by filtering the return of JSONP? In what way am I *unable* to filter the results of JSONP that I can with ss-proxies... if for instance I use jQuery and define a callback $.get("blah.php?callback=?",function(data) { filter(data) }); how is that any different than a SS-proxy?
Nucleon
JSONP is expected to return something like this `callback({"some":"data"});`, where callback is the function name you specify. But the callback name is just convention. If the server wants, it could just return `sendCookieToAttacker(document.cookie);` and the function you pass to JQuery would never execute. You are implicitly trusting the server to invoke the callback function, but there is absolutely no guarantee that it will be called.
sri
In that example SRI, sendCookieToAttacker() would have to defined already otherwise it would accomplish nothing, right? In addition, it would have to be defined in a persistent manner, otherwise it would only affect the hackers client correct?
Nucleon
It doesn't have to be defined elsewhere. He could return this - `function sendCookieToAttacker(cookieValue) {/*Some Code*/}; sendCookieToAttacker(document.cookie); callback({/*Whatever data you were expecting*/};`. This way, your cookies would be stolen, and you wouldn't come to know of it because your app would still work as expected.
sri
Keep in mind that this isn't a nebulous danger that may arbitrarily strike. The JSONP endpoint must be compromised or participate in the attack. The question stated that both ends of the request would be fully trusted/controlled, so things like undesired code injection won't be an issue here.
Dave Ward
Sri: Ok I ran a test and you are correct. The key element is that the JSONP return is *automatically* called no matter what, making filtering it impossible against an attacker. I thought that it was simply pulling data, where it still required a script on my end to execute it, which is incorrect. Dave: Correct, I'm just inquiring to fully understand the concept and the dangers of it, which don't apply to this specific application, but fall into the "more you know" category.So in summary: JSONP and Script tags hold equal danger, ss-proxy allow moderate filtering.
Nucleon
@Dave - The OP implied that filtering would work the same with JSONP and standard AJAX, and that is what I attempted to clarify.
sri