Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apparent jsonp xss vulnerability

Some of our customers have chimed in about a perceived XSS vulnerability in all of our JSONP endpoints, but I disagree as to whether or not it actually constitutes a vulnerability. Wanted to get the community's opinion to make sure I'm not missing something.

So, as with any jsonp system, we have an endpoint like:

http://foo.com/jsonp?cb=callback123

where the value of the cb parameter is replayed back in the response:

callback123({"foo":"bar"});

Customers have complained that we don't filter out HTML in the CB parameter, so they'll contrive an example like so:

http://foo.com/jsonp?cb=<body onload="alert('h4x0rd');"/><!--

Obviously for a URL that returns the content type of text/html, this poses a problem wherein the browser renders that HTML and then executes the potentially malicious javascript in the onload handler. Could be used to steal cookies and submit them to the attacker's site, or even to generate a fake login screen for phishing. User checks the domain and sees that it's one he trusts, so he goes agead and logs in.

But, in our case, we're setting the content type header to application/javascript which causes various different behaviors in different browsers. i.e. Firefox just displays the raw text, whereas IE opens up a "save as..." dialog. I don't consider either of those to be particularly exploitable. The Firefox user isn't going to read malicious text telling him to jump off a bridge and think much of it. And the IE user is probably going to be confused by the save as dialog and hit cancel.

I guess I could see a case where the IE user is tricked into saving and opening the .js file, which then goes through the microsoft JScript engine and gets all sorts of access to the user's machine; but that seems unlikely. Is that the biggest threat here or is there some other vulnerability that I missed?

(Obviously I'm going to "fix" by putting in filtering to only accept a valid javascript identifier, with some length limit just-in-case; but I just wanted a dialog about what other threats I might have missed.)

like image 338
Mike Ruhlin Avatar asked Jan 05 '12 22:01

Mike Ruhlin


People also ask

What is JSONP vulnerability?

JSONP is vulnerable to the data source replacing the innocuous function call with malicious code, which is why it has been superseded by cross-origin resource sharing (available since 2009) in modern applications.

What is JSONP used for?

JSONP is a method for sending JSON data without worrying about cross-domain issues. JSONP does not use the XMLHttpRequest object. JSONP uses the <script> tag instead.

How can you test whether the website is vulnerable to XSS or not?

Analyze Input Vectors Analyze each input vector to detect potential vulnerabilities. To detect an XSS vulnerability, the tester will typically use specially crafted input data with each input vector. Such input data is typically harmless, but trigger responses from the web browser that manifests the vulnerability.

What is JSONP injection?

JSON injection occurs when: Data from an untrusted source is not sanitized by the server and written directly to a JSON stream. This is referred to as server-side JSON injection. Data from an untrusted source is not sanitized and parsed directly using the JavaScript eval function.


2 Answers

Their injection would have to be something like </script><h1>pwned</h1>

It would be relatively trivial for you to verify that $_GET['callback'] (assuming PHP) is a valid JavaScript function name.

The whole point of JSONP is getting around browser restrictions that try and prevent XSS-type vulnerabilities, so to some level there needs to be trust between the JSONP provider and the requesting site.

HOWEVER, the vulnerability ONLY appears if the client isn't smartly handling user input - if they hardcode all of their JSONP callback names, then there is no potential for a vulnerability.

like image 66
Jonathan Rich Avatar answered Sep 18 '22 21:09

Jonathan Rich


Your site would have an XSS vulnerability if the name of that callback (the value of "cb") were derived blindly from some other previously-input value. The fact that a user can create a URL manually that sends JavaScript through your JSONP API and back again is no more interesting than the fact that they can run that same JavaScript directly through the browser's JavaScript console.

Now, if your site were to ship back some JSON content to that callback which used unfiltered user input from the form, or more insidiously from some other form that previously stored something in your database, then you'd have a problem. Like, if you had a "Comments" field in your response:

callback123({ "restaurantName": "Dirty Pete's Burgers", "comment": "x"+alert("haxored")+"y" })

then that comment, whose value was x"+alert("haxored")+"y, would be an XSS attack. However any good JSON encoder would fix that by quoting the double-quote characters.

That said, there'd be no harm in ensuring that the callback name is a valid JavaScript identifier. There's really not much else you can do anyway, since by definition your public JSONP service, in order to work properly, is supposed to do whatever the client page wants it to do.

like image 34
Pointy Avatar answered Sep 18 '22 21:09

Pointy