web-dev-qa-db-ja.com

PHPコードをHTML5のJavaScriptに直接渡す

PHP文字列を直接JavaScript変数に渡し、サーバーの負荷を最小限に抑えたいと思います。PHPファイルに次のJavaScriptを含めますこれを行うため:

_<!DOCTYPE html>
<html>
...
<body>

<section id="section1"></section>

<script>
var example = <?php json_encode($string_var, JSON_HEX_TAG);?>;
example.replace(/[<>]/g, (m) => {return m == "<"? "&lt;" : "&gt;";});
document.getElementById('section1').innerHTML = example;
</script>

...
</body>
</html>
_

PHPからの変数_$string_var_は、がいかなる方法でもサニタイズされなかったユーザー入力です(それはつまり、私はhtmlspecialchars()も実行していません)。

私の例は安全ですか?または、_json_encode_、つまり_JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS_にこれらすべてのフラグを使用する必要がありますか?この例はベストプラクティスに従っていませんが、具体的なリスクや脆弱性はありますか?

参考文献:

  1. _JSON_HEX_TAG_を使用する理由
  2. PHPの_JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS_のフラグ_json_encode_を推奨する回答:
7
flen

JSON_HEX_TAG

(例のように)HTMLドキュメント内のJSにエコーしている場合、これは必然的であるか、巨大なXSS脆弱性を開く危険があります。これがないと、攻撃者は次のように何かを投稿できます。

</script>alert("XSS");</script>

PHP 5.4以降、これは修正され、デフォルトでスラッシュがエスケープされますが、それでも、コードが実行されるPHPバージョンはわかりません。安全性が向上しています。ごめんなさい。

OPが指摘するように、決してPHPのバージョンではない場合でも、<!--を挿入してページ全体を台無しにすることができ、予期しない動作を引き起こす可能性があります。したがって、すべての= PHPバージョン。

JSON_HEX_QUOTおよびJSON_HEX_APOS

これが何をするかを理解するには、次の例を見てください。

$array = array(
    "a" => "'",
    "b" => '"',
);

// This will output {"a":"'","b":"\""}
echo json_encode($array);

// This will output {"a":"\u0027","b":"\u0022"}
echo json_encode($array, JSON_HEX_QUOT | JSON_HEX_APOS);

そのため、文字列リテラルを囲む引用符は決してエンコードされません。文字列リテラル内の引用符は、フラグなしでエスケープされ、フラグ付きでエンコードされます。

あなたの参照によると、これは、出力をイベントハンドラー内で安全に使用できるようにするために使用されます(HTML属性など)。スクリプトタグ内で厳密に必要なわけではないことは事実ですが、イベントハンドラーで安全であることは完全には正しくありません。

たとえば、次の例を見てください。

<?php $data = array(" onmouseenter=alert(1) " => "foo"); ?>
<a onclick="x = <?= json_encode($data, JSON_HEX_QUOT | JSON_HEX_APOS); ?>">test</a>

その結果:

<a onclick="x = {" onmouseenter=alert(1) ": "foo"}">test</a>

属性値を常に一重引用符で囲んでも安全だと思いますが、それでも少し危険を感じます。

JSON_HEX_AMP

引用 あなたの参照 ここ:

XHTMLの非CDATAスクリプトブロックとの互換性のために、&も実行します。

したがって、HTML5を実行しているため、これは当てはまりません。また、いずれにしてもセキュリティの脆弱性はないと思います。それでも、エンコードに支障はありません。

結論

  • HTML5のスクリプトタグ内で使用する場合は、JSON_HEX_TAGを使用するだけで十分です。
  • 属性(イベントハンドラー)の内部でこれを行うことは、少なくとも一重引用符で囲まない限り危険です。
  • 私があなたなら、4つのフラグすべてを使用するsafe_json_encodeという小さなヘルパー関数を作成し、それをスクリプトタグでのみ使用します。必要以上にエンコードしても害はありません。

その他のメモ

  • 正しいコンテンツタイプと文字エンコーディングでページを提供するようにしてください。これを台無しにすると、エンコーディングをバイパスする方法につながる可能性があります。
  • 後で変数の値をHTMLに出力する場合は、XSSについてもう一度考える必要があります。 JSONの値を使用する。 innerHTMLまたはdocument.writeは安全ではありません。 (スクリプトの2行目でこれに対処しているようです。)

免責事項:これは私が今日行った研究に基づいています。私は違いますPHP第一人者です。重要なことをこれに依存している場合は、ここで何かを見逃していないことを確認するために、あなた自身でさらに調査したいと思うでしょう。

8
Anders