クライアントから送信されたデータをそのまま JavaScript 内で使用することは、さまざまなセキュリティ上のリスクを含む。
最も一般的なものは、クロスサイトスクリプティング(XSS)攻撃と呼ばれるもので、これにより攻撃者が悪意のあるスクリプトを埋め込むことができる。
<?php if ($_SERVER['REQUEST_METHOD'] === 'POST'): ?>
<script> var hoge = '<?php echo $_POST[ 'hoge' ] ?>'; </script>
<?php endif; ?>
これはサニタイズ処理を行うことで、これらのリスクを大幅に軽減することが可能である。
PHPでの一般的な方法は、htmlspecialchars 関数を使用することである。
これは、特殊文字をHTMLエンティティに変換することで、その特殊文字がスクリプトとして実行されるのを防ぐ。
<script>
var hoge = '<?php echo htmlspecialchars($_POST['hoge'], ENT_QUOTES, 'UTF-8') ?>';
</script>
ここで使用している htmlspecialchars の第二引数は ENT_QUOTES で、これによりシングルクォートとダブルクォートが共にエスケープされる。
第三引数は文字エンコーディングで、多くの場合 ‘UTF-8’ を使用するはずだ。
しかし、これだけでは JavaScript のコンテキストでのエスケープが適切に行われていないため、依然としてXSS攻撃に対して脆弱である。
なぜなら、HTMLエンティティをエスケープするだけでは、JavaScript 内部での特殊文字を防ぐことができないからである。
これを避けるためには、以下のようにJSONエンコーディングを使用することが一般的である。
<script>
var hoge = JSON.parse('<?php echo json_encode($_POST['hoge'], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE); ?>');
</script>
この方法では、PHPの json_encode 関数を用いてデータをJSON形式にエンコードする。
そして、ブラウザ側では JSON.parse を用いてそのエンコードされたデータをJavaScriptのオブジェクトに変換する。
文字列がダブルクォーテーションで囲まれるため、JavaScript側ではシングルクォーテーションで囲う必要はない。
json_encode の第二引数である JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE は、各種の特殊文字を適切にエスケープする。
このようにすることで、HTML と JavaScript の両方でのセキュリティを確保することができる。
しかし、これでも完全なソリューションではなく、JavaScript に直接 PHP 変数をエコーすること自体がリスクを伴うため、可能な限り避けるべきである。
セキュリティを強化するためのより良い方法は、サーバーサイド(PHP)とクライアントサイド(JavaScript)を明確に分離し、AJAX を使用してサーバーからデータを取得することです。これにより、HTML と JavaScript の間で動的にデータを交換することができ、JavaScript 内で直接 PHP を使用する必要がなくなる。