Is there any risk in not validating the name of a function used in JSONP?

2

Generally, when you make a service JSONP one of the things to be passed by parameter is the name of the callback that will be used in javascript.

Example:

$dados = [1, 2, 3];

$json = json_encode($dados);

$callback = $_GET['callback'];

printf('%s(%s)', $callback, $json);

Requisition:

jsonp.php?callback=my_function

Result:

my_function([1, 2, 3]);

However, my concern is whether the value passed as callback is a value of a valid javascript function.

Is this really something that I should worry about?

    
asked by anonymous 07.08.2015 / 17:32

2 answers

6
Absolutely! Although the person at the highest risk is the page that uses your service (after you you could inject malicious code into it), there are attacks that take advantage of the fact that the server does not sanitize its entries. The wikipedia list some of them . I'll give you 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 this attack is to explore sites that reflect arbitrary content back sent to them. The browser , seeing the malicious content arrive from the legitimate site, acts on that content without question. This is an example of the confused deputy attack .

In the case of JSONP what an attacker can do is limited, but I found an example that uses this protocol. I'll try to summarize it here (you can not anonymize it - since the article is publicly available and easily retrievable - but I'll avoid citing the actual service here because I'm not sure if this vulnerability has already been fixed):

  • Your site has a JSONP API for any information:

    http://example.com/api/jsonp?callback=myCallback
    
  • It does not validate the function name, allowing arbitrary code execution:

    http://example.com/api/jsonp?callback=alert%28document.cookie%29%3Bfoo{}
    

    Executes in the browser of the user:

    alert(document.cookie);
    foo{}( resposta do jsonp );
    

    Okay, the user's cookies have been accessed, but until then anyone with problems is just the site that made the request, not yours ...

  • HTML5 has an attribute for the element a - download - which causes the user to click the link instead of the browser to take you to a page, a download starts . According to documentation it supports even URIs of type blob: and data: ! (Note: I do not know the implications of this on security, and in any case it is not relevant to this case.)

    Suppose such a link is created by pointing to your site's JSONP API:

    <a href="http://example.com/api/jsonp?callback=algo_malicioso" download="instalador.exe">Link legal!</a>
    

    If your site cheerfully reflects this content back, a download will start in the user's browser , reported as coming from your site , but the content was partially provided by the attacker (who can figure out what you've posted back, according to the specific syntax of the file he wants to return).

All that the attacker needs to do is convince some people (in a phishing process, for example) to access that link and open the returned file. Note that even the most attentive users will look at the URL and find that it is indeed a pro link to your site and the browser itself will also consider this when applying your security policies for downloads.

OK, validate is accurate, but how?

As Marco Aurelio has already commented on your answer , the more validation you make the more restricted will be the way To use your service (the client wants objetoGlobal.array[42].objeto.metodo , but you only accept simple callbacks, it is required to create a new global function). However, this should not be a big problem - just the script define the new global function, with a unique and random name, and remove it at the end of execution. A simple validation like suggested regex seems to me of good size.

You could also "violate JSONP rules" 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 is harder - but not impossible - to act on content that is in the middle of an expression, not at the beginning). I'm not saying it's necessarily a good idea , just raising a possibility ...

In the end, the ideal is to avoid JSONP whenever possible. Have you evaluated the possibility of using CORS? Allowing arbitrary domains to access your server is always a risk, and you would have to plan accordingly (eg not only rely on cookies to determine whether a user is logged in), but at least in that case you would be dealing only with < data , which are much simpler to manage than code , as well as not getting tethered back to something received from the client.

    
21.09.2015 / 21:57
4

You can validate the called function, but this will restrict the use of your service.

An attack could occur as a way to inject code into some page, where the javascript (jsonp) return code would be executed. But the code on that page would already be compromised by letting anything go. The problem would be on the page, not the service.

You could restrict use to just names. Something like this regular expression:

^[A-Za-z_][A-Za-z0-9_]*$ 

read: Name must start with a lowercase or uppercase character, or an underscore, followed by multiple text or numeric characters or underscore.

I think other characters could be added without much trouble, like the dot, for example.

But a major security problem lies in the application that is using your service, because it allows you to inject code into the page or to be a malicious page. Even if you filter your service, there may be others available for the attack. Or the attacked page might have more code with wrappers in the form of a valid function.

If the problem is data security, you might be able to add service access control and encryption.

    
19.09.2015 / 01:24