我正在尝试清理和XSS证明来自客户端的一些HTML输入。我正在使用Python 2.6和Beautiful Soup。我解析输入,剥离不在白名单中的所有标签和属性,并将树转换回字符串。
...然而
>>> unicode(BeautifulSoup('text < text'))
u'text < text'
对我来说,这看起来不像是有效的HTML。使用我的标签剥离器,它打开了各种各样的肮脏的方式:
>>> print BeautifulSoup('<<script></script>script>alert("xss")<<script></script>script>').prettify()
<
<script>
</script>
script>alert("xss")<
<script>
</script>
script>
<script></script>
对将被移除,剩下的不仅是XSS攻击,甚至也是有效的HTML。
显而易见的解决方案是将所有<
字符替换为<
字符,在解析后,发现它们不属于标记(类似于>&'"
)。但是Beautiful Soup documentation只提到实体的解析,而不是生成它们。当然,我可以在所有NavigableString
节点上运行替换,但由于我可能会遗漏某些内容,我宁愿让一些经过验证的代码完成这项工作。
默认情况下,为什么美丽的汤不会逃脱<
(以及其他魔术角色),我该怎么做呢?
N.B。我也看了lxml.html.clean
。它似乎是在黑名单的基础上工作,而不是白名单,所以它对我来说似乎不太安全。标签可以列入白名单,但属性不能,并且它允许我的品味太多属性(例如tabindex
)。此外,它在输入AssertionError
上提供<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>
。不好。
其他清理HTML方法的建议也非常受欢迎。我不是世界上唯一尝试这样做的人,但似乎没有标准的解决方案。
答案 0 :(得分:6)
我知道这是原始问题后的3。5年,但您可以使用formatter='html'
argument to prettify()
, encode()
, or decode()
生成结构良好的HTML。
答案 1 :(得分:2)
lxml.html.clean.Cleaner
类允许您使用allow_tags
参数提供标记白名单,并使用带有safe_attrs_only
参数的feedparser中的预计算属性白名单。并且lxml肯定会在序列化时正确处理实体。