4.16 Web APIにまつわる問題
JSON（JavaScript Object Notation）とは
JSONはJavaScriptから生まれたデータ記述フォーマットで，真偽値，数値，文字列，null値の組み合わせを持ったハッシュか配列かその両方の、ウェブ関連ではポピュラーなデータフォーマットです。
JavaScriptとの違いを挙げると、JavaScriptでは文字列リテラルを囲うのはシングルクォートでもダブルクォートでも構いませんが，JSONではダブルクォートのみです。
また，JSONではプロパティ名にもダブルクォートが必須です。JavaScriptにはNaNやundefinedなどの値がありますが，JSONには存在しません。
JSONはJavaScriptの曖昧さを排除して、データ記述言語としての精度と，解析のし易さを確保しています。
JavaScriptにネイティブなJSONサポート（JSON.parse，JSON.stringify）が定義されました。特にJSON.stringifyメソッドを使用すれば手軽にJavaScriptのオブジェクトからJSONを出力することができます。
サーバ側のJSON ⇔ オブジェクト （PHP)
json_encode
PHP配列・オブジェクトからJSON文字列を生成
json_decode
JSON文字列をPHP配列に変換JavaScript側のJSON ⇔ オブジェクト
JSON.ｓｔringify
JavaScriptのオブジェクトからJSON文字列を生成
JSON.parse
JSON文字列をJavaScriptのオブジェクトに変換

JSONP（JSON with Padding）とはPaddingは（本来は不要なものの）付け足しという意味です。（JSONPはJSONではないので，JSONPはJSONとしてパースできません）⁠
JSONPはクロスドメインの制限を超えてデータをやり取りするために使用されます。
CORSができる前に異なるオリジンのサーバからデータを取得する方法の１つがJSONPでした。
JSONPはXMLHttpRequestではなく、script要素を用いて外部のJavaScriptを直接実行することにより、データを取得します。
JSON文字列をそのままscript要素で受け取ることができないので、関数呼び出しの形でデータを生成します。

JSONエスケープ不備による脆弱性
Web API においてJSON文字列生成時のエスケープ処理に不備があると、意図しないJavaScriptがJSONデータに混入する場合があります
JSONデコードにeval関数を使っている場合や、JSONPのようにscript要素でＪＳＯＮ文字列を呼び込んでいる場合には、不正なＪａｖａＳｃｒｉｐｔの実行に至ります
JSONエスケープ不備・脆弱性の影響
Ｗｅｂサイト利用者のブラウザ上でのＪａｖａＳｃｒｉｐｔの実行
JSONエスケープ不備・脆弱性の対策①文字列連結によるＪＳＯＮデータ生成をやめ、信頼できるライブラリを用いて、ＪＳＯＮを生成する②eval関数ではなく、ＪＳＯＮ．Parseなどの安全なAPIでJSONを解釈する

JSON直接閲覧によるXSS脆弱性
JSONを返すWeb APIは、通常XMLHttpRequestによるアクセスを想定したものですが、APIが返すレスポンスデータをブラウザで直接閲覧させることで、攻撃が可能になることがあります
JSON直接閲覧によるXSS脆弱性の影響
Ｗｅｂサイト利用者のブラウザ上でのＪａｖａＳｃｒｉｐｔの実行
JSON直接閲覧によるXSS脆弱性の対策①MIMEタイプを正しく設定する②レスポンスヘッダ X-Content-Ｔｙｐｅ-Options:nosniff を出力する③＜、＞ をUnicodeエスケープする
PHPの場合、json_encodeのオプションパラメータで、エスケープが可能
オプション
エスケープ対象文字
エスケープ結果
JSON_HEX_TAG＜＞＼U003C＼U003E
JSON_HEX_AMP＆＼U0026
JSON_HEX_APOS'＼U0029
JSON_HEX_QUOT"＼U0022④XMLHttpRequestなどCORS対応の機能だけから呼び出せるようにする
XMLHttpRequestからのリクエストには、「X-Request-With: XMLHttpRequest」が付与され、script要素からのアクセスには付かないので、その違いによって、不正なアクセスをチェックできますJSONPのコールバック関数名によるXSS脆弱性
JSONPはJSONデータを引数とするコールバック関数呼び出しの形式を取るが、このコールバック関数名を外部から指定できるように構築するケースが多い
これにより、コールバック関数名によるクロスサイトスクリプティングが可能になる場合があります
JSONPのコールバック関数名によるXSS脆弱性の影響
Ｗｅｂサイト利用者のブラウザ上でのＪａｖａＳｃｒｉｐｔの実行
JSONPのコールバック関数名によるXSS脆弱性の対策①コールバック関数名の文字種と文字数を制限する ※ 英数字とアンダースコア「 ‗ 」のみに制限しても問題ないと思われる。＜＞を使えなくする。
②MIMEタイプを正しく設定する ※ JSONPはJSONではなく、JavaScriptなので、text/javascriptですが、MIMEタイプを指定しないと、text/htmlと解釈され、script要素がJavaScriptとして解釈される※ text/javascriptであれば、script要素は解釈されず、実行されることはありません

Web APIのクロスサイトフォージェリ脆弱性
Web APIでもCSRF脆弱性は混入します。
Web APIのクロスサイトフォージェリ脆弱性をつくHTTP通信経路について①GETリクエスト②HTTPフォームでMIMEタイプが（text/plain、application/x-www-form-urlencoded、multipart/form-data）であることを想定していて、MIMEタイプをチェックしていない場合③プリフライトリクエストを必要としないシンプルなリクエストで、MIMEタイプをチェックしていない場合④プリフライトリクエストを必要とするリクエストだが、プリフライトリクエストに対する処理が不適切
Web APIのクロスサイトフォージェリ脆弱性の対策①CSRFトークン（セッション変数にトークンを保持）②２重送信クッキー
問題点：以下①～③が原因で、セッションフィクセイションされる可能性がある ①クッキーモンスターバグ悪用のリスクがある ②サイトにXSS脆弱性がある場合がある ③HTTP強制による漏洩リスクがある③XMLHttpRequestなどCORS対応の機能だけから呼び出せるようにする
XMLHttpRequestからのリクエストには、「X-Request-With: XMLHttpRequest」が付与され、script要素からのアクセスには付かないので、その違いによって、不正なアクセスをチェックできます
問題点：Adobe Flash Player に過去、カスタムリクエストヘッダを許可なく送信できる脆弱性があった（2014年7月に修正済み）

JSONハイジャックの脆弱性
罠サイトの工夫によって、JSONデータを罠サイトのJavaScriptで読み出す手法がJSONハイジャックの脆弱性として、考案されてきて、ブラウザ側の対策が取られてきました
今後も新しい手法が見つかることが考えられるので、以下の対策が必要です
JSONハイジャックによるXSS脆弱性の対策①レスポンスヘッダ X-Content-Ｔｙｐｅ-Options:nosniff を出力する②XMLHttpRequestなどCORS対応の機能だけから呼び出せるようにする
XMLHttpRequestからのリクエストには、「X-Request-With: XMLHttpRequest」が付与され、script要素からのアクセスには付かないので、その違いによって、不正なアクセスをチェックできます

CORSの検証不備
オリジンの制限をかけないのは情報漏洩のリスクになる NG
オリジンを指定する
OK

Access-Control-Allow-Origin: *Access-Control-Allow-Origin: example.jp

CORS規定では、XMLHttpRequestリクエストのWithCredentialｓプロパティを指定した場合、 Access-Control-Allow-Originヘッダにオリジンを指定しなければならないが、手抜きが多い

・基礎
4g-002 :JSONによる時計【ブラウザ】

【サーバ： 4g/4g-002.html 】【サーバ： 4g/4g-001.php 】

【ブラウザ→サーバ： リクエスト 4g/4g-002.html → レスポンス 】

【ブラウザ→サーバ： リクエスト 4g/4g-001.php → レスポンス 】

4g-004 :JSONPによる時計【サーバ： 4g/4g-004.html 】【サーバ： 4g/4g-003.php 】

【ブラウザ→サーバ： リクエスト 4g/4g-004.html → レスポンス 】

【ブラウザ→APIサーバ： リクエスト 4g/4g-003.php → レスポンス 】

4g-005 :JSONPによる時計(jQuery)【サーバ： 4g/4g-005.html 】【サーバ： 4g/4g-003.php 】

【ブラウザ→サーバ： リクエスト 4g/4g-005.html → レスポンス 】

【ブラウザ→サーバ： リクエスト js/jquery-3.2.1.min.js → レスポンス 】【ブラウザ→APIサーバ： リクエスト 4g/4g-003.php → レスポンス 】

・JSONエスケープの問題
4g-002 :JSONによる時計【ブラウザ】【サーバ： 4g/4g-007.html 】【サーバ： 4g/4g-006.php 】

【ブラウザ→サーバ： リクエスト 4g/4g-007.html → レスポンス 】

【ブラウザ→サーバ： リクエスト js/jquery-3.2.1.min.js → レスポンス 】

【ブラウザ→APIサーバ： リクエスト 4g/4g-006.php → レスポンス 】

4g-002 :JSONによる時計【ブラウザ】

【サーバ： 4g/4g-007.html 】【サーバ： 4g/4g-006.php 】

【ブラウザ→APIサーバ： リクエスト 4g/4g-006.php → レスポンス 】

4g-007a:JSONエスケープの対策版(XSS攻撃)【ブラウザ】【サーバ： 4g/4g-007a.html 】【サーバ： 4g/4g-006a.php 】

【ブラウザ→サーバ： リクエスト 4g/4g-007a.php → レスポンス 】

【ブラウザ→サーバ： リクエスト 4g/4g-006a.php → レスポンス 】

・JSON直接閲覧によるXSS
4g-011 :JSON直接閲覧【ブラウザ】【サーバ： 4g/4g-011.php 】

【ブラウザ→サーバ： リクエスト 4g/4g-011.php → レスポンス 】

4g-011 :JSON直接閲覧(XSS攻撃)【ブラウザ】【サーバ： 4g/4g-011.php 】

JSONを返すので、MIMEタイプは application/json にすべきですが、指定していないので、デフォルトの text/html を返します
そのため、JavaScriptが実行されてしまいます【ブラウザ→サーバ： リクエスト 4g/4g-011.php → レスポンス 】【ブラウザ→サーバ： リクエスト 4g/4g-011.php → レスポンス 】

4g-011a:JSON直接閲覧(Content-Type設定版)(IE9以前ならXSS可能)【ブラウザ】【サーバ： 4g/4g-011a.php 】

application/json を正しく指定しているが、/a.html（PATHINFO)を指定して、IEがContent-Typeを正しく判断しない脆弱性をついています
ＩＥ９以前ではＪａｖａＳｃｒｉｐｔが実行されて、攻撃が成功します
レスポンスヘッダ X-Content-Type-Options:nosniff を出力するとＪａｖａＳｃｒｉｐｔ実行を回避できます
この設定でも、ＩＥ７以前ではJａｖａＳｃｒｉｐｔは実行されてしまいます【ブラウザ→サーバ： リクエスト 4g/4g-011a.php → レスポンス 】

4g-011b:JSON直接閲覧(X-Content-Type-Options: nosniff設定版)(IE7以前ならXSS可能)【ブラウザ】【サーバ：4g/4g-011b.php 】

application/json を正しく指定しているが、/a.html（PATHINFO)を指定して、IEがContent-Typeを正しく判断しない脆弱性をついています
ＩＥ９以前ではＪａｖａＳｃｒｉｐｔが実行されて、攻撃が成功します
レスポンスヘッダ X-Content-Type-Options:nosniff を出力するとＪａｖａＳｃｒｉｐｔ実行を回避できます
この設定でも、ＩＥ７以前ではJａｖａＳｃｒｉｐｔは実行されてしまいます【ブラウザ→サーバ： リクエスト 4g/4g-011b.php → レスポンス 】

4g-011c:JSON直接閲覧(タグ等もエスケープ)(IE7でもJavaScriptは実行されない)【ブラウザ】【サーバ： 4g/4g-011c.php 】

application/json を正しく指定しているが、/a.html（PATHINFO)を指定して、IEがContent-Typeを正しく判断しない脆弱性をついています
ＩＥ９以前ではＪａｖａＳｃｒｉｐｔが実行されて、攻撃が成功します
レスポンスヘッダ X-Content-Type-Options:nosniff を出力するとＪａｖａＳｃｒｉｐｔ実行を回避できます
この設定でも、ＩＥ７以前ではJａｖａＳｃｒｉｐｔは実行されてしまいます
PHPの場合、json_encodeのオプションパラメータで、 [ ＜ ＞ ］ をUnicodeエスケープできるので、ＩＥ７以前でも JａｖａＳｃｒｉｐｔ の実行を回避できます【ブラウザ→サーバ： リクエスト 4g/4g-011c.php → レスポンス 】

4g-011d:JSON直接閲覧(X-Requested-Withヘッダの確認; 403 Forbiddenとなる)【ブラウザ】【サーバ： 4g/4g-011d.php 】

XMLHttpRequestからのリクエストには、「X-Request-With:XMLHttpRequest」

application/json を正しく指定しているが、/a.html（PATHINFO)を指定して、IEがContent-Typeを正しく判断しない脆弱性をついています
ＩＥ９以前ではＪａｖａＳｃｒｉｐｔが実行されて、攻撃が成功します
レスポンスヘッダ X-Content-Type-Options:nosniff を出力するとＪａｖａＳｃｒｉｐｔ実行を回避できます
この設定でも、ＩＥ７以前ではJａｖａＳｃｒｉｐｔは実行されてしまいます
PHPの場合、json_encodeのオプションパラメータで、 [ ＜ ＞ ］ をUnicodeエスケープできるので、ＩＥ７以前でも JａｖａＳｃｒｉｐｔ の実行を回避できます
さらに左吹き出しの対処を追加しています【ブラウザ→サーバ： リクエスト 4g/4g-011d.php → レスポンス 】

4g-012 :4g-011d.phpの呼び出し(jQuery利用)【ブラウザ】【サーバ： 4g/4g-012.html 】

【ブラウザ→サーバ： リクエスト 4g/4g-012.html → レスポンス 】

【ブラウザ→サーバ： リクエスト js/jquery-3.2.1.min.js → レスポンス 】

【ブラウザ→サーバ： リクエスト 4g/4g-011.php → レスポンス 】
jQueryなどの著名なＪａｖａＳｃｒｉｐｔライブラリは、XMLHttpRequertによるＨＴＴＰリクエストに、X-Request-Withヘッダを付与する

・JSONPコールバック関数名によるXSS
4g-016 : JSONPコールバック関数名によるXSS(HTMLからの正常系利用)【ブラウザ】【サーバ： 4g/4g-016.html 】【サーバ： 4g/4g-015.php 】

【ブラウザ→サーバ： リクエスト 4g/4g-016.html → レスポンス 】【ブラウザ→APIサーバ： リクエスト 4g/4g-015.php → レスポンス 】

4g-015 : JSONPコールバック関数名によるXSS(攻撃でない直接閲覧)【ブラウザ】【サーバ： 4g/4g-015.php 】【ブラウザ→APIサーバ： リクエスト 4g/4g-015.php → レスポンス 】

4g-015 : JSONPコールバック関数名によるXSS(XSS攻撃)【ブラウザ】【サーバ： 4g/4g-015.php 】

JSONＰはJSONではなく、ＪａｖａＳｃｒｉｐｔそのままなので、MIMEタイプは text/javascript にすべきですが、指定していないので、デフォルトの text/html を返します
そのため、JavaScriptが実行されてしまいます【ブラウザ→APIサーバ： リクエスト 4g/4g-015.php → レスポンス 】

4g-015 : JSONPコールバック関数名によるXSS(XSS攻撃)【ブラウザ】【サーバ： 4g/4g-015a.php 】

コールバック関数名の文字種と文字数を制限しています※ 英数字とアンダースコア「 ‗ 」のみに制限しても問題ないと思われる。＜＞を使えなくする。

MIMEタイプを正しく設定する
text/javascript とすると、レスポンスをＨＴＭＬとして解釈しないので、script要素は解釈されず、JavaScriptとしても実行されません【ブラウザ→APIサーバ： リクエスト 4g/4g-015a.php → レスポンス 】