是否需要将JSON中的HTML编码为HEX?

时间:2017-08-30 03:02:44

标签: javascript php json character-encoding xss

在我的网站中,来自用户输入的任何html标记都被htmlspecialchars转义,然后我使用PHP json_encode将html标记+转义的用户内容作为JSON变量发送,这样就可以“转义为” “,只有我放在html中的那些,因为用户输入已经被转义。

这很好用,我没有问题,我看不出XSS攻击怎么可能,我试过了。

但是我看到Twitter和facebook编码为HEX所有html标签,所以如果我这样做,我会将选项JSON_HEX_TAG JSON_HEX_AMP JSON_HEX_APOS JSON_HEX_QUOT添加到json_encode()

那么为什么twitter和facebook这样做以及为什么我应该这样做?我无法创建安全错误。

2 个答案:

答案 0 :(得分:0)

从XSS的角度来看,您的策略听起来不错。十六进制编码可能支持其他语言/字符集?

答案 1 :(得分:0)

通常,您需要转义括号和引号,因为它们可以逃脱周围的html上下文。 json_encode本身仅在您输出到' .js'文件周围没有任何HTML。

这两种方法都可以阻止XSS,但不同之处在于它们会产生不同的输出。 htmlspecialchars转换'<'到'& lt;' (一个html实体)和十六进制编码转换'<'到' \ u003C' (JavaScript字符串文字转义序列)。如果您要将数据发送到JavaScript变量,那么您希望使用JavaScript来确保数据的完整性。

假设您要发送消息"一个月的时间"到JavaScript。

使用十六进制编码,您可以写:

<script>
    var input = <?php
        $input = "One month's time";

        $input = json_encode($input, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);

        echo $input;
    ?>;
    console.log(input);
</script>

它会输出&#34;一个月的时间&#34;,如你所愿。

使用htmlspecialchars,您可以写:

<script>
    var input = <?php
        $input = "One month's time";

        $input = htmlspecialchars($input, ENT_QUOTES, "utf-8");
        $input = json_encode($input);

        echo $input;
    ?>;
    console.log(input);
</script>

它将输出&#34;一个月&#039;时间&#34;,它已损坏数据。这是因为它的HTML编码但未直接插入HTML上下文。

如果要设置innerHTML属性或类似属性,则应使用HTML编码,但要防止基于DOM的XSS,但这可以使用JavaScript而不是PHP来完成。