JSONP

JSONP (Web)

[5] JSONP は、JSONJavaScript関数の呼び出しの引数として記述する (関数名括弧で括る) ことによって異なる起源要求を送信し、 応答を受信する技法です。

[6] CORS が実装される前に同一起源ポリシーの抜け道として広く Webアプリケーションによって利用されていました。 セキュリティーホールの温床であることもあり、現在ではあまり使われず、 CORS を利用するのが一般的となっています。

代替

[34] JSONP はほぼセキュリティーホールであり、望ましくないと考えられています。

[39] 元々公開されていて漏洩してもまったく問題のないデータならセキュリティー問題にはなりませんが、 古い時代の裏技的な手法ですから、今時敢えて使うメリットはまったくありません。 問題があるかないか微妙な場合に判断を誤るリスクを考えると、 避けておくのが無難でしょう。

[40] Webブラウザー上で異なる起源のデータを取得するには、 Fetch API を使うことができます。 Fetch API に対応していない Webブラウザーを想定するなら、 XHR を使うことができます。

[41] サーバーで異なる起源からのデータの取得に対応させるには、 CORS を使う必要があります。

構文

[35] JavaScript としても解釈可能な JSON データを JavaScript 関数呼び出しの形で表現したものと理解されています (が、 正式な規定はなく、厳密な定義は不明です)。

  1. *
    1. 空白
  2. 関数名
  3. *
    1. 空白
  4. (
  5. JSONテキスト
  6. )
  7. *
    1. 空白

callback 引数

[10] JavaScript関数名は、 URLquery 部 (application/x-www-form-urlencoded) の callback 引数によって指定されたものを使うことが慣例となっています。

[11] JSONP は通常は (その用途からしても) GET で使うものですが、 POST でも要求を受け付けている場合、 要求メッセージメッセージ本体application/x-www-form-urlencodedmultipart/form-datacallback 引数でも指定を受け付けることがあります。

[12] 関数名として任意の文字列を受け付けると、任意の JavaScript コードの注入を許してしまうことになり、脆弱性となります。 JSONP の生成者は関数名として使える文字を限定し、 使えない文字が含まれているとエラー応答を返したり、 既定の関数名で返したりする必要があります。実装によっては通常の JSON を返すかもしれません。

[26] その範囲は実装により異なります。 JavaScript 側のライブラリーの仕様にもよります。 オブジェクトの階層の深いところにある関数を呼び出すために . を、 配列内の関数を呼び出すために [] を認めることもあります。

[13] callback 引数やそれに相当する指定がない場合の動作は実装により異なります。 通常の JSON で返すことやエラーの応答を返すこともあれば、既定の関数名で返すこともあります。

JSON との互換性

[14] JSONJavaScriptオブジェクトリテラルは、 厳密には構文的に違いがあります。 (JSON の項を参照。) ですからただ単に JSON の前後に関数名括弧を連結するだけでは、 正しい JavaScript コードとならず、構文エラーになる可能性があります。

[15] これを避けるためには、 JSON の生成時、または JSON から JSONP への変換時にいくつかの文字エスケープしなければなりません。 しかしそれをしていない実装もあり、ある種の脆弱性となるかもしれません。

[27] 実際に JSONP を使った Webアプリケーションには特定の文字を入力として与えると誤動作するものがあります。

MIME 型

[7] JSONPJavaScript のコードですから、 text/javascript が適切と考えられます。

[8] JSONPJSON の変種であるとして、 application/json が指定されることもあります。

[29] この指定は必ずしも正しいとは言えませんが、 application/json を表示するビューアーの類の中には JSONP に対応しているものもあり、 有用なこともあるかもしれません。

[9] また text/htmltext/plainContent-Type: なしなどで送信されることもあります。

[28] text/htmltext/plain を使うのは明らかに誤りであり、避けるべきです。

[30] いずれにせよ、 charset 引数が指定されることもあります。

JSONP による情報漏洩

[16] JSONP に含まれる情報が秘密の情報である場合、第三者に情報が漏洩する危険性があります。

[17] 例えばある会員制サイトが、アクセスした利用者自身の会員登録情報を返す JSONP を用意しているとします。 悪意のあるサイトはその JSONP を取得して内容を自サイトに送信するコードを書くことで、 同サイトを閲覧した利用者が気づかないうちに会員制サイトの登録情報を取得できます。

JSONP による CSRF

[18] JSONP は異なる起源要求を送信し、特定の処理を実行してその結果を得るために用いられることがあります。 その素朴な実装は、 CSRF 脆弱性そのものです。

[19] 特に、 JSONP では特定の URLGET だけで処理を実行させられますから、 JavaScript の記述や実行が認められていなくても、 img 要素src 属性に指定するなどより簡易な方法で呼び出せてしまいますので、 より深刻な問題となる可能性があります。

[20] 例えば URL に指定した文字列を掲示板に投稿できる JSONP API が存在するとします。また、 JavaScript は記述できないものの、 末尾が .jpgURL を貼り付けると img 要素に変換される SNS があるとします。 JSONPURL の末尾が .jpg になるようにし、 SNS に貼り付けると、その SNS を表示するたびに、利用者が気づかないうちに自動的に掲示板に投稿されてしまいます。

歴史

[21] JSONP は、2005年12月5日に Bob Ippolitoブログで提案 >>4 しました。呼称の由来は「JSON with Padding」>>4 だといいます。

[23] なお query引数の名前は jsonp >>4 とされていました。 後に普及することになる callback はまだ使われていませんでした。

[24] JSONPデファクト標準であり、仕様書と呼べるものは存在していません。

[25] 個別の Web API の実装仕様の類を除けば、 JSONP を採用している仕様には次のものがあります。

[31] Draft 1: OAuth Extension for Response Data Format - Draft 1 ( 版) <http://oauth.googlecode.com/svn/spec/ext/response_data_format/1.0/drafts/1/oauth_response_data_format_ext.html#processing>

When requesting the response data format as "JSON", the Consumers MAY pass the 'xoauth_json_callback' with the JSONP callback and the Service Provider MUST return a JSONP callback using the value from the 'xoauth_json_callback' parameter.

[10] Instagram API Endpoints • Instagram Developer Documentation ( 版) <https://instagram.com/developer/endpoints/#jsonp>

If you're writing an AJAX application, and you'd like to wrap our response with a callback, all you have to do is specify a callback parameter with any API call:

[11] Responses & Errors ( 版) <https://developer.foursquare.com/overview/responses>

To use JSONP, add a callback=XXX parameter to your request and we will respond with XXX(response). In the case of JSONP, we always return 200 (except in the case of 500’s) so the brower will allow the response to be handled by your code, but the true HTTP response code can be obtained from the code in the meta response.

[32] Response Formats ( 版) <http://pic.photobucket.com/dev_help/WebHelpPublic/Content/Getting%20Started/ResponseFormats.htm>

To use, set "format=jsonp", and specify a callback function name in the jsonp_callback parameter. The callback can be word characters and dot, supporting OO code.

[33] WooCommerce REST API Documentation v2 ( 版) <http://woothemes.github.io/woocommerce-rest-api-docs/#jsonp-support>

You can specify the callback using the ?_jsonp parameter for GET requests to have the response wrapped in a JSON function:

[38] JSON callbacks | Alfresco Documentation ( 版) <http://docs.alfresco.com/4.2/concepts/ws-json-callbacks.html>

A callback is invoked by adding the following URL query parameter to the web script request:

alf_callback=<function>

[42] Abusing JSONP with Rosetta Flash ( (Michele Spagnuolo著, )) <https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/>

To be also protected from content sniffing attacks, prepend the reflected callback with /**/. This is exactly what Google, Facebook and GitHub are currently doing.

[43] JSONP Sandboxを使ったXSS - 金利0無利息キャッシング – キャッシングできます - subtech () <https://subtech.g.hatena.ne.jp/mala/20140120/1390227002>

[44] カーセンサー | APIリファレンス | リクルートWEBサービス () <https://webservice.recruit.co.jp/carsensor/reference.html>

format レスポンス形式 レスポンスをXMLかJSONかJSONPかを指定します。JSONPの場合、さらにパラメータ callback=コールバック関数名 を指定する事により、javascript側コールバック関数の名前を指定できます。   初期値:xml。xml または json または jsonp。