Absolutely! Although those who are at greatest risk are the page that uses your service (after all you could inject malicious code into it), there are attacks that take advantage of the fact that the server does not sanitize its entries. wikipedia list some of them. Let me give just one example, which should be enough to realize the importance of validating what your server sends to the user.
Reflected File Download
The idea behind of that attack is to explore websites that reflect back arbitrary content sent to them. The browser, seeing malicious content arrive from the legitimate site, acts on that content without question. It is an example of confused Deputy Attack.
In the case of JSONP what an attacker can do is limited, but I found an example that uses that protocol. I will try to summarize it here (there is no way to anonymize it - since the article is publicly available and easily retrievable - but I will avoid quoting the real service here because I am not sure whether this vulnerability has been fixed or not):
Your website has a JSONP API for any information:
http://example.com/api/jsonp?callback=myCallback
It does not validate the function name, allowing to execute arbitrary code:
http://example.com/api/jsonp?callback=alert%28document.cookie%29%3Bfoo{}
Executes in the browser user’s:
alert(document.cookie);
foo{}( resposta do jsonp );
Okay, the user’s cookies have been accessed, but so far who’s in trouble is just the site that made the request, not yours...
HTML5 has an attribute for the element a
- download
- which causes when the user click on the link instead of the browser take you to a page, a download is started. Second the documentation it even supports Uris of the type blob:
and data:
! (Note: I don’t know the implications of this on safety, and in any case it’s not relevant to this case)
Suppose such a link is created pointing to your website’s JSONP API:
<a href="http://example.com/api/jsonp?callback=algo_malicioso" download="instalador.exe">Link legal!</a>
If your site cheerfully reflects that content back, a download will be started on browser user, reported as coming from your website, but the contents of it were partially provided by the attacker (who can find a way to ignore what you posted back, according to the specific syntax of the file he wants to return).
All the attacker needs to do then is convince some people (in a process of phishing for example) accessing this link and opening the returned file. Note that even the most attentive users will look at the URL and find that in fact it is a pro link your website... And the browser you will also consider this when applying your download security policies.
Okay, validate is accurate, but how?
As Marco Aurelio has already commented on your answer, the more validation you do the more restricted will be the way to use your service (the client wants objetoGlobal.array[42].objeto.metodo
, but you only accept callbacks simple, it is obliged to create a new global function). However, this shouldn’t be a big problem - just define the new global function, with a random and unique name, and remove it at the end of the run. A simple validation like the regex suggested seems to me good size.
You could also "violate JSONP rules" in order to make it more difficult to exploit vulnerabilities of this type. Instead of returning:
callback({ ... });
you could return:
;(function() { callback({ ... }); })();
and the result should be the same (and it becomes more difficult - but not impossible - to act on a content that is in the middle of an expression, not at its beginning). I’m not saying it’s necessarily a good idea, just raising a possibility...
After all, the ideal is to avoid JSONP whenever possible. Have you considered the possibility of using CORS? Allowing arbitrary domains to access your server is always a risk, and you would have to plan accordingly (e.g., not rely solely on cookies to determine whether or not a user is logged in), but at least in that case you would only be dealing with dice, which are much simpler to manage than code, besides not being tied to echoing back something received from the customer.
But the goal of
JSONP
does not return the name of a pre-defined function on the requesting page ?– Edilson