【发布时间】:2017-01-04 17:35:09
【问题描述】:
我想将 JSON 的内容存储在 HTML 文档的源代码中,在脚本标记内。
该 JSON 的内容确实取决于用户提交的输入,因此需要非常小心地为 XSS 清理该字符串。
我在 SO 上阅读了两个概念。
1。将所有出现的</script 标记替换为<\/script,或将所有</ 替换为<\/ 服务器端。
代码如下所示(以 Python 和 jinja2 为例):
// view
data = {
'test': 'asdas</script><b>as\'da</b><b>as"da</b>',
}
context_dict = {
'data_json': json.dumps(data, ensure_ascii=False).replace('</script', r'<\/script'),
}
// template
<script>
var data_json = {{ data_json | safe }};
</script>
// js
access it simply as window.data_json object
2。将数据编码为 HTML 实体编码的 JSON 字符串,并在客户端进行 unescape + 解析。 Unescape 来自这个答案:https://stackoverflow.com/a/34064434/518169
// view
context_dict = {
'data_json': json.dumps(data, ensure_ascii=False),
}
// template
<script>
var data_json = '{{ data_json }}'; // encoded into HTML entities, like < > &
</script>
// js
function htmlDecode(input) {
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
var decoded = htmlDecode(window.data_json);
var data_json = JSON.parse(decoded);
此方法不起作用,因为脚本源中的 \" 在 JS 变量中变为 "。此外,它创建了一个更大的 HTML 文档,而且也不是真正的人类可读,所以如果它不意味着巨大的安全风险,我会选择第一个。
使用第一个版本是否存在安全风险?使用 .replace('</script', r'<\/script') 清理 JSON 编码的字符串是否足够?
参考SO:
Best way to store JSON in an HTML attribute?
Why split the <script> tag when writing it with document.write()?
Script tag in JavaScript string
Sanitize <script> element contents
Escape </ in script tag contents
关于这个问题的一些很好的外部资源:
Flask 的 tojson 过滤器的实现 source
Rail 的 json_escape 方法的 help 和 source
在 Django ticket 和 proposed code 中进行了长达 5 年的讨论
【问题讨论】:
-
您应该将
<、>和&编码为 HTML 实体。 -
我花了一个小时写这个问题,包括参考我找到的所有以前的 SO 答案。收到一个单行和一个关闭 / -1 感觉根本没有帮助。
-
至少
JSON.stringify()和 Python 的json.dumps()不会将/转义为\/。我正在寻找一种自动化方式,它使用脚本标记解析器来解码 JSON 或字符串上的JSON.parse()。在服务器端手动转义也需要在客户端手动进行。 -
自上次评论以来,我发现 Flask 中的
|tojson过滤器实现是最好的资源。源代码以及一些非常重要的 cmets 都写在那里。 github.com/pallets/flask/blob/…我对正确方法的理解如下:1.使用方法1.来自我的问题。 2. 将 、& 和 ' 编码为 u00 形式(不是 HTML 实体!)。 3. 仔细检查 JSON 编码器是否转义 `\`,因为它取决于不同的实现(有时甚至会更改中间版本)。 -
请参阅 archive.oreilly.com/pub/a/actionscript/excerpts/as3-cookbook/… 以获取 、&、引号和斜杠的“u00”替代列表。
标签: javascript python html json xss