Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

JSONP for cross-site Callbacks


:P
On this page:

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.

Posted in AJAX  ASP.NET  HTML  JavaScript  

The Voices of Reason


 

# DotNetSlackers: JSONP for cross-site Callbacks


Bertrand Le Roy
July 04, 2007

# re: JSONP for cross-site Callbacks

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.

Rick Strahl
July 05, 2007

# re: JSONP for cross-site Callbacks

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.

Peter Bromberg
July 05, 2007

# re: JSONP for cross-site Callbacks

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.

Rick Strahl
July 06, 2007

# re: JSONP for cross-site Callbacks

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.

Rick Strahl
July 06, 2007

# re: JSONP for cross-site Callbacks

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.

Atif Aziz
October 03, 2007

# re: JSONP for cross-site Callbacks

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?" ;)

TweeZz
October 10, 2007

# re: JSONP for cross-site Callbacks

Isn't your json wrong? :)

{ "x": 10; "y": 15} should be { "x": 10, "y": 15} I think..

Jokin Cuadrado
October 11, 2007

# re: JSONP for cross-site Callbacks

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)

Rick Strahl
January 08, 2008

# re: JSONP for cross-site Callbacks

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.

Paul
December 15, 2008

# re: JSONP for cross-site Callbacks

Hey Parvinder, any luck getting the web service to work without using Proxy?

Craig Lebowitz
December 20, 2008

# re: JSONP for cross-site Callbacks

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.

Jonathan Ranes
January 23, 2009

# re: JSONP for cross-site Callbacks

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.

Jonathan Ranes
January 23, 2009

# re: JSONP for cross-site Callbacks

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.

headtech
March 02, 2009

# re: JSONP for cross-site Callbacks

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).

Rick Strahl
March 02, 2009

# re: JSONP for cross-site Callbacks

@headtech - 'normal' ajax doesn't work cross-domain. JSONP does... and it's quiet as long as your page code implements required handler.

James Hart
March 20, 2009

# re: JSONP for cross-site Callbacks

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.

Rick Strahl
March 20, 2009

# re: JSONP for cross-site Callbacks

@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.

Paul Elia
March 31, 2009

# re: JSONP for cross-site Callbacks

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.

Trey Carroll
April 06, 2009

# re: JSONP for cross-site Callbacks

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.

jsonx
August 03, 2009

# re: JSONP for cross-site Callbacks

thanks for perfect explanation

pawan
August 29, 2009

# re: JSONP for cross-site Callbacks

Hi Rick
I having the same problem what parvinder is having.And have no idea how to get it solve.Pls help

pawan

LOVE_MOSS_NOT
October 10, 2009

# re: JSONP for cross-site Callbacks

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..

purab kharat
October 27, 2009

# re: JSONP for cross-site Callbacks

Jsonp code not working in IE7 browser....How to solve that

Julian
November 05, 2009

# re: JSONP for cross-site Callbacks

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.

Ms.justenoughtobedangerous
December 04, 2009

# re: JSONP for cross-site Callbacks

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. :)

Aamir Hasan
January 11, 2010

# re: JSONP for cross-site Callbacks

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

adnan
June 26, 2010

# re: JSONP for cross-site Callbacks

Here is a detailed description on how jsonp works. Hope it'll help you.

http://abcoder.com/javascript/jquery/jsonp-first-timer/

karl
July 20, 2010

# re: JSONP for cross-site Callbacks

Thanks:

This response works also:
Response.Write(Callback + "( {x:10 , y:100} );");

Surya
September 27, 2010

# re: JSONP for cross-site Callbacks

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

Scrutinous
September 16, 2011

# re: JSONP for cross-site Callbacks

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.

Tord Nordell
May 30, 2012

# re: JSONP for cross-site Callbacks

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?

Rick Strahl
May 30, 2012

# re: JSONP for cross-site Callbacks

@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 - 2024