flawopen.com/JSONの解析/JSON.parse() vs eval()
JSON.parse()はeval()より安全ですか?
入力をメモにたとえると、JSON.parse()は構造化されたフォームの項目を読み取りますが、eval()はメモを実行すべき指示としてインタープリターに渡します。JSON.parse()はJSON文法に従い、テキスト内のJavaScriptを実行しません。それでも、解析後の値は使用前に検証が必要です。
// 信頼できないデータをソースコードとして解釈しない。
const data = eval("(" + untrustedJson + ")");
const data = JSON.parse(untrustedJson);
// JSONをデータとして解析。不正なJSONはSyntaxErrorを投げる。
この疑問が生まれる理由
JSON.parse()が広く使われる前、一部の古いJavaScriptコードはJSONを読むためにeval()を使っていました。JSONテキストとJavaScript式の構文に重なりがあるためです。この方法はJavaScriptプログラムを評価するので、攻撃者が制御する入力がJSON値に限定されず、コードとして扱われる可能性があります。JSONの読み取りにはJSONパーサーを使いましょう。
JSON.parse()でも防げないこと
JSON.parse()は業務ルールを検証せず、操作を認可せず、解析した値をHTML、SQL、シェルコマンド、URLで安全に使える状態にも変えません。期待するデータ構造を検証し、文脈に合った出力エンコードやパラメーター化APIを使ってください。reviverを渡す場合、アプリケーションが提供したコールバックは解析中に実行されます。信頼できる単純な処理にし、攻撃者が制御する値による副作用を避けてください。
よくある質問
JSONテキスト自体はデータとして解析され、JavaScriptとして実行されません。ただしアプリケーションがreviverを渡すと、信頼されたコールバックが解析値ごとに呼び出され、コードを実行できます。攻撃者が制御するデータに、実行可能なコールバック処理を選択・構築させないでください。
いいえ。解析結果をアプリケーションの期待するスキーマと認可ルールに照らして検証してください。HTMLには出力エンコード、SQLにはパラメーター化クエリを使います。解析はこれらの文脈に対するサニタイズではありません。