/
219.txt
96 lines (71 loc) · 5.72 KB
/
219.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
[5] [DFN[[[JSONP]]]] は、[[JSON]] を [[JavaScript]] の[[関数]]の呼び出しの[[引数]]として記述する
([[関数名]]と[[括弧]]で括る) ことによって異なる[[起源]]に[[要求]]を送信し、
[[応答]]を受信する技法です。
[6] [[CORS]] が実装される前に[[同一起源ポリシー]]の抜け道として広く
[[Webアプリケーション]]によって利用されていました。
[[セキュリティーホール]]の温床であることもあり、現在ではあまり使われず、
[[CORS]] を利用するのが一般的となっています。
* JSON との互換性
[14] [[JSON]] と [[JavaScript]] の[[オブジェクトリテラル]]は、
厳密には構文的に違いがあります。 ([[JSON]] の項を参照。)
ですからただ単に [[JSON]] の前後に[[関数名]]と[[括弧]]を連結するだけでは、
正しい [[JavaScript]] コードとならず、構文エラーになる可能性があります。
[15] これを避けるためには、 [[JSON]] の生成時、または [[JSON]] から [[JSONP]]
への変換時にいくつかの[[文字]]を[[エスケープ]]しなければなりません。
しかしそれをしていない実装もあり、ある種の[[脆弱性]]となるかもしれません。
* [CODE(URI)@en[callback]] 引数
[10] [[JavaScript]] の[[関数名]]は、 [[URL]] の [[query]] 部
([CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]) の
[DFN[[CODE(URI)@en[[[callback]]]]]] [[引数]]によって指定されたものを使うことが慣例となっています。
[11] [[JSONP]] は通常は (その用途からしても) [CODE(HTTP)@en[[[GET]]]]
で使うものですが、 [CODE(HTTP)@en[[[POST]]]] でも[[要求]]を受け付けている場合、
[[要求メッセージ]]の[[メッセージ本体]]の [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
や [CODE(MIME)@en[[[multipart/form-data]]]] の [CODE(URI)@en[[[callback]]]]
[[引数]]でも指定を受け付けることがあります。
[12] [[関数名]]として任意の文字列を受け付けると、任意の [[JavaScript]]
コードの注入を許してしまうことになり、[[脆弱性]]となります。
[[JSONP]] の生成者は[[関数名]]として使える[[文字]]を限定し、
使えない[[文字]]が含まれていると[[エラー]]の[[応答]]を返したり、
既定の[[関数名]]で返したりする必要があります。
[13] [CODE(URI)@en[[[callback]]]] [[引数]]やそれに相当する指定がない場合の動作は実装により異なります。
エラーの[[応答]]を返すこともあれば、既定の[[関数名]]で返すこともあります。
* MIME 型
[7] [[JSONP]] は [[JavaScript]] のコードですから、 [CODE(MIME)@en[[[text/javascript]]]]
が適切と考えられます。
[8] [[JSONP]] は [[JSON]] の変種であるとして、 [CODE(MIME)@en[[[application/json]]]]
が指定されることもあります。
[9] また [CODE(MIME)@en[[[text/html]]]] や
[CODE(MIME)@en[[[text/plain]]]]、 [CODE(HTTP)@en[[[Content-Type:]]]]
なしなどで送信されることもあります。
* JSONP による情報漏洩
[16] [[JSONP]] に含まれる情報が秘密の情報である場合、第三者に情報が漏洩する危険性があります。
[EG[
[17] 例えばある会員制サイトが、アクセスした[[利用者]]自身の会員登録情報を返す [[JSONP]]
を用意しているとします。
悪意のあるサイトはその [[JSONP]] を取得して内容を自サイトに送信するコードを書くことで、
同サイトを閲覧した利用者が気づかないうちに会員制サイトの登録情報を取得できます。
]EG]
* JSONP による CSRF
[18] [[JSONP]] は異なる[[起源]]に[[要求]]を送信し、特定の処理を実行してその結果を得るために用いられることがあります。
その素朴な実装は、 [[CSRF]] [[脆弱性]]そのものです。
[19] 特に、 [[JSONP]] では特定の [[URL]] の [CODE(HTTP)@en[[[GET]]]] だけで処理を実行させられますから、
[[JavaScript]] の記述や実行が認められていなくても、 [CODE(HTMLe)@en[[[img]]]]
[[要素]]の [CODE(HTMLa)@en[[[src]]]] [[属性]]に指定するなどより簡易な方法で呼び出せてしまいますので、
より深刻な問題となる可能性があります。
[EG[
[20] 例えば [[URL]] に指定した文字列を[[掲示板]]に投稿できる [[JSONP]]
[[API]] が存在するとします。また、 [[JavaScript]] は記述できないものの、
末尾が [CODE[[[.jpg]]]] の [[URL]] を貼り付けると [CODE(HTMLe)@en[[[img]]]]
[[要素]]に変換される [[SNS]] があるとします。 [[JSONP]] の [[URL]] の末尾が
[CODE[[[.jpg]]]] になるようにし、 [[SNS]] に貼り付けると、その [[SNS]]
を表示するたびに、[[利用者]]が気づかないうちに自動的に[[掲示板]]に投稿されてしまいます。
]EG]
* 歴史
[3] [CITE@en[JSONP: JSON With Padding - Ajaxian]]
( ([TIME[2011-12-03 15:06:37 +09:00]] 版))
<http://ajaxian.com/archives/jsonp-json-with-padding>
[4] [CITE@en[Remote JSON - JSONP]]
( ([[Bob Ippolito]] 著, [TIME[2013-09-18 23:18:57 +09:00]] 版))
<http://bob.ippoli.to/archives/2005/12/05/remote-json-jsonp/>
[1] [CITE[TAKESAKO @ Yet another Cybozu Labs: Operaでも非同期リクエストが並列処理できる img-JSONP]] ([TIME[2008-11-26 11:37:10 +09:00]] 版) <http://labs.cybozu.co.jp/blog/takesako/2007/06/opera_img-jsonp.html>
[2] [CITE[JSONP が Opera だと非同期処理できない - 川o・-・)<2nd life]] ([TIME[2009-02-09 18:00:12 +09:00]] 版) <http://d.hatena.ne.jp/secondlife/20060906/1157515075>