LoginSignup
3
1

More than 1 year has passed since last update.

【XSS】PHPからJSへ配列を渡しJSON.parseで解析すると脆弱性があるよという話

Last updated at Posted at 2022-08-24

はじめに

追記 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>

結果、alert ダイアログが表示されます。
alertダイアログ.png

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>

結果、きちんとconsoleに表示されました!
console.png

番外編: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>

結果、三つともconsoleに表示されました。
console2.png

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1