27

I'm having trouble connecting some dots having recently learned of JSONP. Here's my understanding:

  • Cross-domain XmlHttpRequests for any content (including JSON) is banned, due to the same origin policy. This protects against XSRF.
  • You are permitted to have a script tag with a src that returns JSONP - some JSON padded inside a call to a Javascript function (say 'Foo')
  • You can have some implementation of 'foo' on the page that will get called when the JSONP data is returned, and you can do things with the JSON data that function is passed

Why is it OK to receive cross-domain data if it came via JSONP, but not if it came via JSON?

Is there an assumption that JSON is prone to permitting XSRF but JSONP is not? If so, is there any reason for that other than JSONP being some de-facto data format that won't ever provide data that enables XSRF? Why JSONP and not some arbitrary root tag on XML instead?

Thank you in advance for your answers, please make my brain work again after failing to figure this one out.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
snappieT
  • 544
  • 6
  • 16
  • JSONP is only as safe as the server that's serving up the jsonp text. Nothing says the jsonp server can't send over malicious code/data. jsonp's purely used to get around the same-origin policy. it's got all the same risks as a regular json string, plus the added bonus of being actual JS code, not just js data. – Marc B Aug 18 '11 at 17:16
  • 1
    I should clarify my explicit question. If it's possible to retrieve JSON data cross-domain through the use of JSONP (when I say 'safe', I mean that browsers allow it), why is it not equally OK to retrieve JSON data cross-domain through other mechanisms, such as XmlHttpRequest? – snappieT Aug 19 '11 at 08:45
  • Now that most browsers have a native json implementation to encode/decode the strings, it's not as big of a deal... but initially json support was accomplished via an eval(), so you'd be RUNNING the string that was returned, not just processing it. – Marc B Aug 19 '11 at 14:18
  • JSONP is just a consensual XSS attack. We bypass the same origin restriction by simply injecting a script from the remote domain. The remote domain could, in theory, use this script to hack all your users and gain complete control over your site. Use with caution. – superluminary Jun 13 '16 at 11:38

2 Answers2

10

I understand this question to be about why the browser considers JSONP safe, not about whether it is safe (which it isn't). I will address this question step by step.

Regular ol' AJAX

To perform a regular AJAX request, the browser creates an XHR object, points it at the URL and pulls the data. The XHR object will only trust data from the same domain. This is a hard limitation. There is no getting round it in current browsers (edit - you can now use CORS).

Solution - Don't use XHR

Since XHR is subject to the same domain poilicy, we can't use XHR to do cross domain AJAX. Luckily, there are other ways to hit a remote server. We could append an image tag to the page for example. We can also append a script tag and give it a src attribute that points to the remote server. We can pull JQuery from a CDN for example and expect it to work.

How JSONP works.

When we make a JSONP request, our code dynamically appends a script tag to the page. The script tag has a source attribute which points to the remote JSONP API url, just as though you were inserting a script from a CDN.

The JSONP script returned by the server is wrapped in a function call. When the script is downloaded, the function will be executed automatically.

This is why we have to tell the JSONP the name of the callback function we want to wrap the script in. That function will be called once the script has downloaded.

Security concerns

There are some fairly big security concerns here. The script you are downloading could take control over your page and put your users at risk. JSONP is not safe for your users, it is just not blocked by the web browsers. JSONP really is a browser exploit which we are taking advantage of. Use with caution.

Used wisely, JSONP is pretty awesome though.

superluminary
  • 47,086
  • 25
  • 151
  • 148
7

I don't know how the perception that JSONP is safe came up but see

JSON-P is, for that reason, seen by many as an unsafe and hacky approach to cross-domain Ajax, and for good reason. Authors must be diligent to only make such calls to remote web services that they either control or implicitly trust, so as not to subject their users to harm.

and

The most critical piece of this proposal is that browser vendors must begin to enforce this rule for script tags that are receiving JSON-P content, and throw errors (or at least stop processing) on any non-conforming JSON-P content.

both quotes from http://json-p.org/ .

other links with some useful information about JSONP/security:

all these tell 2 things - basically it is not considered "safe" but there are ideas on how to make it "safer"... though most ideas rely on standardization AND specific check logic to be built into browsers etc.

Community
  • 1
  • 1
Yahia
  • 69,653
  • 9
  • 115
  • 144
  • 1
    Ah, let me be a bit clearer with what I mean by 'safe'. Browsers don't let you perform cross-domain XmlHttpRequests because the browser doesn't consider it as 'safe'. But you can do cross-domain JSONP requests, which allow you to get cross-domain JSON. What is 'unsafe' about JSON (for the purposes of XSRFs, I presume) that is safe about JSONP? – snappieT Aug 19 '11 at 11:50
  • 2
    absolutely nothing - it just happens that according to the standard there is no "same origin policy" for ` – Yahia Aug 19 '11 at 14:05