我正在尝试清理和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只提到了实体的解析,而不是它们的产生 . 当然我可以在所有节点上运行替换,但由于我可能会错过一些东西,我宁愿让一些经过测试和测试的代码完成这项工作 .
Why doesn't Beautiful Soup escape < (and other magic characters) by default, and how do I make it do that?
注:我也看了 lxml.html.clean
. 它似乎是在黑名单的基础上工作,而不是白名单,所以它对我来说似乎不太安全 . 标签可以列入白名单,但属性不能,并且它允许我的品味太多属性(例如 tabindex
) . 此外,它在输入 <SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>
上给出 AssertionError
. 不好 .
其他清理HTML方法的建议也非常受欢迎 . 我不是世界上唯一尝试这样做的人,但似乎没有标准的解决方案 .
2 回答
我知道在原始问题之后这是3.5yrs,但您可以使用formatter='html' argument to prettify(), encode(), or decode()生成格式良好的HTML .
lxml.html.clean.Cleaner
类允许您使用allow_tags
参数提供标记白名单,并使用带有safe_attrs_only
参数的feedparser中的预计算属性白名单 . 并且lxml肯定会在序列化时正确处理实体 .