hyp*_*not 11 html javascript python xss json
我想在脚本标记内的HTML文档源中存储JSON的内容.
该JSON的内容确实取决于用户提交的输入,因此需要非常小心地为XSS清理该字符串.
我在这里读了两个概念.
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
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
此方法不起作用,因为\"在"JS变量中的脚本源中.此外,它创建了一个更大的HTML文档,也不是真正的人类可读,所以如果它不意味着巨大的安全风险,我会选择第一个.
使用第一个版本是否存在安全风险?是否足以清理JSON编码的字符串.replace('</script', r'<\/script')?
参考SO:
在HTML属性中存储JSON的最佳方法?
为什么在使用document.write()编写<script>标记时将其拆分?
JavaScript字符串中的脚本标记
Sanitize <script>元素内容
Escape </ in script标记内容
关于这个问题的一些很好的外部资源:
Flask的tojson过滤器的实现源
Rail的json_escape方法的帮助和来源
Django 票证和建议的代码长达5年的讨论
以下是我处理此问题中相对较小的部分的方法,即在脚本元素中存储 JSON 的编码问题。简而言之,您必须转义它们中的一个<或/一起终止脚本元素 - 即使在 JSON 字符串文字中也是如此。您无法对脚本元素的实体进行 HTML 编码。您可以通过 JavaScript 反斜杠转义斜杠。我更喜欢 JavaScript-hex-escape 小于尖括号作为\u003C.
.replace('<', r'\u003C')我在尝试从oembed结果传递 json 时遇到了这个问题。其中一些包含脚本关闭标签(未提及Twitter 的名称)。
json_for_script = json.dumps(data).replace('<', r'\u003C');
Run Code Online (Sandbox Code Playgroud)
这变成data = {'test': 'foo </script> bar'};了
'{"test": "foo \\u003C/script> bar"}'
Run Code Online (Sandbox Code Playgroud)
这是不会终止脚本元素的有效 JSON。
我从Jinja模板引擎中的这个小宝石中得到了这个想法。这是您使用过滤器时运行的内容。{{data|tojson}}
def htmlsafe_json_dumps(obj, dumper=None, **kwargs):
"""Works exactly like :func:`dumps` but is safe for use in ``<script>``
tags. It accepts the same arguments and returns a JSON string. Note that
this is available in templates through the ``|tojson`` filter which will
also mark the result as safe. Due to how this function escapes certain
characters this is safe even if used outside of ``<script>`` tags.
The following characters are escaped in strings:
- ``<``
- ``>``
- ``&``
- ``'``
This makes it safe to embed such strings in any place in HTML with the
notable exception of double quoted attributes. In that case single
quote your attributes or HTML escape it in addition.
"""
if dumper is None:
dumper = json.dumps
rv = dumper(obj, **kwargs) \
.replace(u'<', u'\\u003c') \
.replace(u'>', u'\\u003e') \
.replace(u'&', u'\\u0026') \
.replace(u"'", u'\\u0027')
return Markup(rv)
Run Code Online (Sandbox Code Playgroud)
(您可以使用\x3C代替\u003C,这可以在脚本元素中使用,因为它是有效的 JavaScript。但最好还是坚持使用有效的JSON。)
首先,你的偏执是有根据的。
是的,对所有可能混淆所涉及的不同解析器的字符进行编码会“更安全”。保持其可读性可能与您的安全范例相矛盾。
注意:JSON 字符串编码的结果应该是规范的和 OFC,而不是破坏的,如可解析的。JSON 是 JS 的子集,因此可以被 JS 解析,没有任何风险。因此,您所要做的就是确保提取 JS 代码的 HTML-Parser 实例不会被您的用户数据欺骗。
所以真正的陷阱是两个解析器的嵌套。实际上,我强烈建议您将类似的内容放入单独的请求中。这样你就可以完全避免这种情况。
假设在这样的解析器中可能发生所有可能的样式和错误纠正,其他标签(打开或关闭)可能会实现类似的壮举。
如:向解析器建议脚本标记已隐式结束。
因此,建议以您选择的任何可逆方法对斜杠和所有标记大括号(/、<、>)进行编码,而不仅仅是脚本标记的结束,只要它不会混淆 HTML 解析器即可:
</script片段总之,是的,最好进行一些更改,但请注意,通过首先尝试类似的操作,您将距离“安全”一步之遥,而不是通过 XHR 加载 JSON 或至少使用像base64这样严格的字符串编码。
PS:如果您可以从其他人的编码字符串的代码中学习,那就太好了,但是如果“库”或其他人的函数不能完全满足您的需要,您不应该求助于它们。因此,宁愿编写并彻底测试您自己的(解码/编码)编码器,并知道这个陷阱已被密封。
| 归档时间: |
|
| 查看次数: |
1139 次 |
| 最近记录: |