Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

JSONP for cross-site Callbacks


JSONP is an unofficial protocol that allows making cross domain calls by generating script tags in the current document and expecting a result back to calls a specified callback handler.

The client JavaScript code to make a JSONP call looks like this:

function jsonp(url,callback,name, query)
{                
    if (url.indexOf("?") > -1)
        url += "&jsonp=" 
    else
        url += "?jsonp=" 
    url += name + "&";
    if (query)
        url += encodeURIComponent(query) + "&";   
    url += new Date().getTime().toString(); // prevent caching        
    
    var script = document.createElement("script");        
    script.setAttribute("src",url);
    script.setAttribute("type","text/javascript");                
    document.body.appendChild(script);
}

The idea is that this code adds a <script> tag dynamically to the page and when this code loads it causes the JavaScript that the server loads to be executed. Because it uses the DOM and a <script> tag this gets around the cross site scripting limitations of the XHR object.

The server is expected to return JSON data, but with a slight twist: It has to prepend the callback function name, which is passed as part of the url. The syntax for a JSONP Url is simply the URL with a jsonp= query string parameter that defines the the callback function:

http://someserver.com/mypage.aspx?jsonp=callbackFunction

If the server wants to return a result like:

{ "x": 10, "y": 15}

the result will be turned into (assuming the callback specified is callbackFunction):

callbackFunction( { "x": 10, "y": 15} )

If you're implementing this in an ASPX.NET page it might look like this:

public partial class JSONP : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(Request.QueryString["jsonp"]) )
            this.JsonPCallback();
    }

    public void JsonPCallback()
    {
        string Callback = Request.QueryString["jsonp"];
        if (!string.IsNullOrEmpty(Callback))
        {
            // *** Do whatever you need
            Response.Write(Callback + "( {\"x\":10 , \"y\":100} );");
        }

        Response.End();
    }
}

The client will now have  script tag that gets added to the document and the script executes on load and in effect calls the callbackFunction with the parameter:

function callbackFunction(Result)
{
    alert(Result.x + "  " + Result.y) ;
}

And there's a cross domain callback.

Note that this callback requires that the server KNOWS it's receiving a JSONP request because the server has to prepend the callback handler name supplied so the code can fire in the client.

Yeah it seems like an Exploit

I'm not sold on the idea, because it is basically exploiting what seems to be a security hole in the browser and one that apparently won't be plugged as many services like Adsense rely on it. But all this talk about preventing cross site scripting are pretty much moot by allowing this sort of hack to work. But then again this implementation doesn't do anything that couldn't be done before or changes any of the security issues - it just takes advantage of this functionality.

Still - it feel... wrong <g>...

It is what it is and it seems this approach is getting more popular in being able to retrieve JSON content from various public sites. It certainly is something that should be useful for ASP.NET developers who internally need to make client callbacks to their own internal sites which seems a frequent request.

Make Donation
Posted in AJAX  ASP.NET  HTML  JavaScript  


Feedback for this Post

 
# DotNetSlackers: JSONP for cross-site Callbacks
by DotNetSlackers Latest ASP.NET News July 04, 2007 @ 3:31pm
# re: JSONP for cross-site Callbacks
by Bertrand Le Roy July 04, 2007 @ 11:40pm
Yes, the problem with JSONP is that you're basically fully trusting the remote site with a permission to execute arbitrary JavaScript on your page. There's absolutely zero validation you can do. That's fine if you're talking to Flickr, but a definite no-go in many mash-up scenarios. That's why so many people are exerting pressions on browser vendors to allow for pure data cross-domain calls using XHR.
# re: JSONP for cross-site Callbacks
by Rick Strahl July 05, 2007 @ 12:19am
But isn't that always the case with any data you retrieve from the server pretty much? Any JSON that comes down and is eval'd has the potential for code execution as well. The real threat I would think is a XSS attack but that's a threat for any number of scenarios and JSONP is not any worse than others.

To me it seems either we should allow XSS or not but there are already those holes via <script> and <iframe> that it doesn't make a lot of sense to have XHR not support cross site too.
# re: JSONP for cross-site Callbacks
by Peter Bromberg July 05, 2007 @ 12:17pm
Rick,
I have railed about this so many times I'm not even going to bother to point to the "places".

If you are going to enforce some sort of "security", it needs to be one that all the browser manufacturers can come together on and implement *Seamlessly* across the board. That means XHR, IFRAME, dynamic script tags, whatever.

There are 2 kinds of people in the world - the casual user - who wants to be "protected" from the bad guys without having to think, and we developers, who love to think.

We lose.
# re: JSONP for cross-site Callbacks
by Rick Strahl July 06, 2007 @ 3:46pm
Peter, yes it would be nice to have it one way or another, but 'browser standards' being what they are moving at slower than a snail don't hold your breath <s>...

The real question to ask is: What is the behavior that we as developers would want without compromising security? XSS is a real threat, but as long as hacks like this exist limiting XHR to not support cross-domain calls just seem silly.
# re: JSONP for cross-site Callbacks
by Rick Strahl July 06, 2007 @ 6:04pm
One more thought on security here that might not be very clear from the discussion above: If you're one of the people who thinks that XSS is not a problem consider that any - ANY JavaScript code control can do what JSONP intends to do but return JS code from an external server and execute it. It is childishly simple IF there's a way to embed script into an input field that gets echo'd back and not properly encoded.

JSONP just exploits that fact and doesn't IMO at least make this problem any worse.
# re: JSONP for cross-site Callbacks
by Atif Aziz October 03, 2007 @ 9:34am
Rick, you're right about one thing...it's childishly simple:
http://widgets.dotnetkicks.com/

So much so, in fact, that if I wanted to even show you the HTML code behind that page by sending the URL to the file in Subversion (as in http://dotnetkicks.googlecode.com/svn/trunk/Widgets/Web/index.html), it gets served up as a web page and becomes fully functional in the browser, doing XSS between domains dotnetkicks.googlecode.com and www.dotnetkicks.com. So childishly simple that there's almost a devlish and wicked feeling to it that you may recall from childhood. Now, it's just the grown up man in you fighting because now you're saying, "We're not supposed to be having this much fun, are we?" ;)
# re: JSONP for cross-site Callbacks
by TweeZz October 10, 2007 @ 10:44pm
Isn't your json wrong? :)

{ "x": 10; "y": 15} should be { "x": 10, "y": 15} I think..
# re: JSONP for cross-site Callbacks
by Jokin Cuadrado October 11, 2007 @ 2:40am
just faced the same needs, with this script an the microsoft.ajax json serializer you have all done.

Shared js As New System.Web.Script.Serialization.JavaScriptSerializer()
js.Serialize(myResponse)
# re: JSONP for cross-site Callbacks
by Rick Strahl January 08, 2008 @ 2:39pm
Tweez, thanks missed that. The server code is right but I accidentally got the JSON literal wrong. Fixed. I also just updated the text with a few additional small notes to clarify a few details I just ran into as I'm revisiting a jsonp callback in an application.
# re: JSONP for cross-site Callbacks
by Paul December 15, 2008 @ 4:19pm
Hey Parvinder, any luck getting the web service to work without using Proxy?
# re: JSONP for cross-site Callbacks
by Craig Lebowitz December 20, 2008 @ 3:11pm
Rick, thanks for the explanation

Note:

The 'callback' argument of the javascript 'jsonp' function does not get used, which is a bit confusing since the server has a local variable Callback in its helper.

Looks like the 'query' argument to jsonp function is used, instead, to indicate the javascript callback function on the client that the server would inject its own arguments for...

Your example is still instructive and very appreciated.
# re: JSONP for cross-site Callbacks
by Jonathan Ranes January 23, 2009 @ 12:01pm
At long last my linq class populated from a complex proc is java serialized sent back from wcf as io.stream to the cross site moded prototype library for my json scriptaculous joy. Big thanks to this blog, most of those ideas come from there.

I will only be serving my application to one client so I just hard coded the call back function into the part of the service that builds the linq class.

There were several times I thought I was stuck for good but now I'm on a roll. Thanks Rick!

p.s. I had gotten all of the above but this, I wondered why in debug mode I could see my data in a file in studio but it never made it back to the success function. Now I know.
# re: JSONP for cross-site Callbacks
by Jonathan Ranes January 23, 2009 @ 1:08pm
Also isn't this an old trick. It seems like I remember doing this hack a long long time ago in the late 90's. I think we called them data islands or something like that. When I saw that data sitting in the dom I had deja vu really bad. I think there were versions of something like json going around back then too.

The big wheel keeps on spinning. I would say Linq and prototype are two pretty good things in combination once you get the hang of them.
# re: JSONP for cross-site Callbacks
by headtech March 02, 2009 @ 8:30pm
So what is missing in all this? What is the difference between this method and a "normal" ajax call?

A "normal" ajax call that uses XMLHttpRequest is quiet. That means the user has no real clue it is even happening.

This method is not. It will show the page as loading in the brower every time you make the call.

This is fine if you are doing it all at the initial page load but quite annoying if you are looking for the Web 2.0 feel.

My $0.02(which is all that's left in my stock portfolio after Obama won).
# re: JSONP for cross-site Callbacks
by Rick Strahl March 02, 2009 @ 8:44pm
@headtech - 'normal' ajax doesn't work cross-domain. JSONP does... and it's quiet as long as your page code implements required handler.
# re: JSONP for cross-site Callbacks
by James Hart March 20, 2009 @ 7:46am
Actually, the real XSS vulnerability you're msising here isn't that the site -consuming- the JSONP data is vulnerable to an attack by the source of the data - after all, a site has to opt in to pulling a JSONP script in from an external site - the danger is actually to the site serving up JSONP.

Look at this bit of your JSONP server code:

Response.Write(Callback + "( {\"x\":10 , \"y\":100} );")


What you're doing there is letting an arbitrary user generate a URL that causes your web app to generate a document containing a string of their choosing. If the string they supply looks, instead of like a javascript function name, like a chunk of arbitrary HTML, well you've just created a user-configured webserver. One that serves up arbitrary webpages from within your domain, with access to your domain's cookies. (note, you're not even setting response contenttype to text/javascript, so serving up HTML from the page is trivial)

Unless you validate that the Callback value is a plain JavaScript identifier, you're creating a huge security hole on your server with that line of code.
# re: JSONP for cross-site Callbacks
by Rick Strahl March 20, 2009 @ 1:54pm
@James - understood. The example, was just that - to demonstrate the mechanics of JSONP. A typical JSONP API would likely force a fixed endpoint callback function rather than allowing the user to provide her own.

I hadn't thought about the Cookie issue though - in fact as you say hadn't thought much about the server vulnerability. I suppose HtmlEncoding any user input would also fix that potential problem of generating output that might contain script code.

Thanks for the perspective I'd missed.
# re: JSONP for cross-site Callbacks
by Paul Elia March 31, 2009 @ 9:52am
Hi Rick,

Long time reader, first time blogger.

I've been using this XSS issue for a while and it works great. The only problem that I have encountered is that Microsoft Internet Explorer (up through version 7 at least) has a limitation on URI lengths of 2083 (and querystrings of 2048 characters). See http://support.microsoft.com/kb/208427 for details. If your generated URI exceeds this length then IE silently decides not to make the HTTP GET request. Ironically, IIS allows 16,384 characters for an HTTP GET request.

All other major browsers have no such restriction or a much higher limit for URI length. See http://www.boutell.com/newfaq/misc/urllength.html for one research report.

Do you know of a way to do XSS with an HTTP(S) POST or any other way to have XSS work in IE when the data that needs to be sent to the server exceeds IE's URL length limit?

I thought about somehow compressing the querystring but to do so effectively in Javascript under IE kind of scares me.
# re: JSONP for cross-site Callbacks
by Trey Carroll April 06, 2009 @ 10:57am
I have set up a JSONP feed and I am concerned by by James Hart's comment above.

As far as I understand it- here is the problem scenario:

A hacker could
1) access someone's machine after they have visited the site
2) use telnet or a low-level application to forge a GET request,
3) inject some javascript to display domain cookies before the callback function name.

All of this is done in order to see the cookies from my site's domain. If the hacker already has physical access to the box, can't they just choose view> cookies?

Please correct me if I am mistaking the process or the problem. I need to make sure that this site is secure.

I have done a lot of research today, but I have not seen any evidence of exploitation of sites using JSONP. (Excepting very obvious SQL-Injection against non-validated query-string parameters.)

I don't store anything except the ASP.NET session auth-cookie - which expires quickly. So, based on these assumptions, I don't believe that this vulnerability affects my application.
# re: JSONP for cross-site Callbacks
by jsonx August 03, 2009 @ 5:29pm
thanks for perfect explanation
# re: JSONP for cross-site Callbacks
by pawan August 29, 2009 @ 4:57am
Hi Rick
I having the same problem what parvinder is having.And have no idea how to get it solve.Pls help

pawan
# re: JSONP for cross-site Callbacks
by LOVE_MOSS_NOT October 10, 2009 @ 10:39pm
Agree.. it feels wrong until Microsoft comes along and calls it something else e.g ActiveAJAX, MAJAX, ServerAjax, CooperationAjax, COMAJAX, ActiveAjax, MashAjax, or something along those lines..

After all, this is web 3.0 stuff , yes 3.0, content should be exchangeable between machines..
# re: JSONP for cross-site Callbacks
by purab kharat October 27, 2009 @ 5:38am
Jsonp code not working in IE7 browser....How to solve that
# re: JSONP for cross-site Callbacks
by Julian November 05, 2009 @ 11:26pm
Just dropping by to point to jquery-jsonp: http://code.google.com/p/jquery-jsonp/

The plugin has nice features that are missing from current jQuery's implementation.
# re: JSONP for cross-site Callbacks
by Ms.justenoughtobedangerous December 04, 2009 @ 2:38pm
I have two questions. I think this is happening to me, but I think mine is intentional . I think somehow this jsonp crap is allowing access to my computer by just getting the script in to my machine. What I need to know is before I can access exactly the problem i need to know exactly what could one gain by using this as a hacking method and how would it be viewed to the one seeing the information. Are there any over the counter dummy books to teach one this or would you have to be a fairly smart techie to set it up....could the data be broken broken down to common terms where any idiot could understand it?

My second question is this? is there any thing out on the market or any secret trick that you can set up a boomerang type retaliation. What I mean is sending them back what they are sending me. I am almost 100 percent sure I know where mine is coming from and I just know enough to be dangerous and illegal on what i can do or cant.

oh and a third question ...sorry, but is there any thing that will let me know in the data that it is bad. I run wire shark and I will often view behind a page and read its source data and pick up a lot of what it is trying to do ,.

....but then again who I am dealing with must not be more than a script kiddie or else I would not have a clue they are with me. :)
# re: JSONP for cross-site Callbacks
by Aamir Hasan January 11, 2010 @ 10:59pm
One advantage of XML that hasn't been mentioned yet is that it is possible to use XSLT to extract data from an XML document using arbitrarily complex XPath expressions. I can't see a way to do this in JSON. How would you find all objects in a JSON document that contain a "currency" field as a direct descendant, irrespective of where the objects occur in the structure? In XML with XSLT/XPath this is very easy.
visit my Blog:Studentacad.com
# re: JSONP for cross-site Callbacks
by adnan June 26, 2010 @ 8:40am
Here is a detailed description on how jsonp works. Hope it'll help you.

http://abcoder.com/javascript/jquery/jsonp-first-timer/
# re: JSONP for cross-site Callbacks
by karl July 20, 2010 @ 1:18pm
Thanks:

This response works also:
Response.Write(Callback + "( {x:10 , y:100} );");
# re: JSONP for cross-site Callbacks
by Surya September 27, 2010 @ 9:10am
Hi All,

Can anyone explain me in detail how i need to call this from Client Side Code.

I already hosted service on some other domain but i am not able to understand how i need to call the same. So I would appreciate if anyone could send me the whole snippet of HTML & JS code which needs to be used to call the service hosted.

The service URL is (for testing) :

http://210.7.74.218/V1_Ser/JSON.aspx?jsonp=callbackFunction

Please revert back ASAP.

Regards
Surya
# re: JSONP for cross-site Callbacks
by Scrutinous September 16, 2011 @ 2:31pm
JSONP is completely safe, to say it's not is preposterous. The owner of the server side must explicitly wrap the json response in the callback value, that can't be hacked in. And if the server side can do that, it can also very well accept and validate api tokens.

So just like XSS, it's up to the app owner to secure their shit.

Saying JSONP is dangerous is retarded.
# re: JSONP for cross-site Callbacks
by Tord Nordell May 30, 2012 @ 7:07am
Is it still a gateway to hell if you apply an id to the script-tag and remove it later on from the DOM when you're done analyzing your padded json?
# re: JSONP for cross-site Callbacks
by Rick Strahl May 30, 2012 @ 8:52am
@Scrutinous - The server has to support JSONP with the resources it serves yes, but the issue is that if you have a malicious client script, it can call a server of its own choosing to phone home basically. JSONP merely limits *what* can be called remotely but in effect it's the perfect tool for XSS attacks.

@Tord - dynamic script tags are yet another way that you can use bypass cross site loading restrictions.
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014