使用 `json_encode` 防止 XSS 攻击

Posted

技术标签:

【中文标题】使用 `json_encode` 防止 XSS 攻击【英文标题】:Using `json_encode` to protect against XSS attacks 【发布时间】:2018-07-16 21:52:29 【问题描述】:

我们最近通过安全分析器运行了我们的项目,并在代码中发现了需要对输入进行转义的区域。对于这个问题,我特别指的是跨站点脚本攻击。分析器建议使用htmlentitiesjson_encode 清理输入,但我不相信json_encode 是适合这项工作的工具。在做了一些研究之后,我完全相信它从来没有打算以这种方式使用,在这方面的任何用处都只是一个副作用。以下是我逃避潜在 XSS 攻击的函数:

function escapeScriptTags($value)

    return json_encode(htmlentities($value), JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS);

我遇到的问题是返回的字符串连接并附加了双引号。这会扭曲用户的输入并导致明显的问题。我发现的一种解决方法是:

function escapeScriptTags($value)

    return trim(json_encode(htmlentities($value), JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS), '"');

由于引号被转义为\u0022,因此删除的任何" 字符将是json_encode 添加的字符。

但正如我所说,我仍然不相信这是在 php 中防止 XSS 攻击的正确方法。是否有更明确的方式来转义用户输入以防止不会更改用户输入的 XSS 攻击?

编辑

在这个特定的例子中,将输入的值写入 HTML,但也有一些情况下我正在写入 javascript。我的问题可能是没有一种万能的 XSS 保护方法。

EDIT2

因此,似乎没有一种万能的方法。为了完整起见,以及任何需要这方面指导的人,这里是我的输入清理功能——包括 SQL 注入保护功能。非常欢迎任何批评或建议:

/**
 * Escapes user input that is to be interpolated into JavaScript code to
 * protect against Cross-Site Scripting (XSS) attacks.
 * 
 * @param $value
 * @return string
 */
function encodeJavaScriptString($value)

    return json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS);


/**
 * Escapes HTML tags to protect against Cross-Site Scripting (XSS) attacks.
 *
 * @param $value
 * @return string
 */
function escapeScriptTags($value)

    return htmlentities($value, ENT_QUOTES, 'UTF-8');


/**
 * Escapes a string in order protect against a SQL injection attack. If `$like` is true,
 * underscores and percent signs are also escaped for use in a`LIKE` clause.
 *
 * @param $value
 * @param \mysqli $mysqli
 * @param bool $like
 * @return string
 */
function escapeSqlString($value, \mysqli $mysqli, $like = false)

    return $like ? addcslashes($mysqli->real_escape_string($value), '%_')
        : $mysqli->real_escape_string($value);

【问题讨论】:

我们需要更多信息来帮助您。您是否将数据输出到 HTML 中?在这种情况下,请使用htmlspecialchars()。您是否将数据输出到 JavaScript 中?在这种情况下,请使用json_encode() 【参考方案1】:

要使用的编码取决于输出格式,因此您应该根据上下文使用json_encodehtmlentities。这意味着转义需要在输出而不是输入上完成。那么添加或修改的任何字符都不会影响系统的其余部分。

当写入 JavaScript 变量时,双引号成为 JavaScript 字符串语法的一部分,不需要删除:

<script>
    console.log(JSON.parse(<?= json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS) ?>));
</script>

写入 html 时,请仅使用 htmlentities

<div>
    <?= htmlentities($value); ?>
</div>

【讨论】:

【参考方案2】:

有很多方法可以解决 XSS 漏洞。

如果有任何易受攻击的脚本保存在数据库中,请确保在显示时对其进行清理以确保它不会在前端执行,请使用以下函数清理输出:

htmlspecialchars($string, ENT_QUOTES, 'UTF-8');

您可以添加 HTTP X-XSS-Protection 响应标头,这是 Internet Explorer、Chrome 和 Safari 的一项功能,可在检测到反射的跨站点脚本 (XSS) 攻击时阻止页面加载。

X-XSS-Protection "1; mode=block"

【讨论】:

以上是关于使用 `json_encode` 防止 XSS 攻击的主要内容,如果未能解决你的问题,请参考以下文章

防止XSS注入的方法

v-html防止XSS注入

xss-[安全盒子王松]

SpringBoot使用mica-xss防止Xss攻击

特殊字符的过滤,防止xss攻击

如何使用过滤器执行输出编码以防止 XSS?