はじめに
追記 2022/08/27
私の記事に間違っている部分がありました…
JSON.parse
自体にXSSの脆弱性があるわけではありません。JSON.parse
の'...'
内に展開するという使い方が間違っているという話でした。
今回でいいますと
// JSON.parseの()内でシングルクォーテーションを使用しているためでした。
// じゃあダブルクォーテーションを使えば良いかというと、そういうわけでもないです。
// ダブルクォーテーションだとエラーになります。
JSON.parse('<?php echo json_encode($array) ?>');
// また、下記の記述でもJSコードが認識されます。
const array = ['<?php echo json_encode($array) ?>'];
そのため、上記を念頭に記事を読んで頂けますと幸いです。
※コメント欄で@tadsanさんに教えて頂きました。@tadsanさんありがとうございます!
また、もう一つの回避策も教えて頂きましたので、ぜひコメント欄を見て頂けますと幸いです。
PHPからJSへ配列を渡しJSON.parse
にかけると脆弱性がある、この話はそこそこ前からある気がします。
ただ、最近もGoogleで検索するとJSON.parse
を使用した記事を目にすることがあります。
そこで、PHPからJSへ配列を渡した時にJSON.parse
を使用しなくても配列を渡せる方法を書いていきます。
JSON.parseで解析するとXSSの脆弱性がある
XSSの脆弱性があるため配列内のJSコードが認識されます。
コードは下記のようなコードです。
<?php
$array = array("',alert('xss'),'");
?>
<!DOCTYPE html>
<html lang="ja">
<head></head>
<body>
<script>
// JSON.parseに読み込まれる値は、'["'、alert('xss')、'"]'、の三つの値になる
const array = JSON.parse('<?php echo json_encode($array) ?>');
console.log(array);
</script>
</body>
</html>
JSON.parseを使用しない方法
じゃあどうやってJSコードではなく文字列として読み込ませるかというとJSON.parse
を外すだけでいけます。
※ちなみに、配列内の要素が文字化けする人はjson_encodeの第二引数で調整できます。詳しくはこちら
<?php
$array = array("',alert('XSS'),'");
?>
<!DOCTYPE html>
<html lang="ja">
<head></head>
<body>
<script>
const array = <?php echo json_encode($array) ?>;
console.log(array);
</script>
</body>
</html>
番外編:Laravelでの書き方
Laravelでは下記のように書くことができます。
<script>
const array1 = <?php echo json_encode($array) ?>;
console.log(array1);
const array2 = {!! json_encode($array) !!};
console.log(array2);
const array3 = @json($array);
console.log(array3);
</script>