要为django应用程序的文本字段创建一个简单而安全的编辑器,我有一个片段来清理输入html到django代码:
from bs4 import BeautifulSoup
def sanitize_html(value):
tag_whitelist = ['img','b','strong','blockquote', 'a']
attr_whitelist = ['src', 'alt', 'width', 'height', 'href','class']
soup = BeautifulSoup(value)
for tag in soup.find_all():
if tag.name.lower() in tag_whitelist:
tag.attrs = { name: value for name, value in tag.attrs.items()
if name.lower() in attr_whitelist }
else:
tag.unwrap()
# scripts can be executed from comments in some cases
try:
comments = soup.find_all(text=lambda text:isinstance(text, Comment))
for comment in comments:
comment.extract()
except:
pass
return unicode(soup)
我还使用此方法将模板字段中的javascript
列入黑名单:
BADLIST = ['javascript']
def no_js (text):
if any(e in text for e in BADLIST):
raise ValidationError("Your text contains bad words!")
else:
return True
另一方面,在模板中我需要使用{{text| safe}}
来显示健康的html标签。
所以我想知道这些约束,输入是否仍然可以被XSS攻击?如果是这样,如何解决它?
答案 0 :(得分:1)
乍一看,代码看起来还不错,但是检查安全漏洞是不容忽视的,需要花费一些时间来自行检查。
例如,测试是否执行了诸如<script>alert('hello')</script>
之类的字符串。除了这种简单的测试外,还有很多东西需要检查。关于此事的文件很多。
此外,正如我的评论所述,我强烈建议您使用已建立的库来清理输入。这样的库是bleach:
Bleach是一个基于白名单的HTML清理和文本链接库。它旨在通过一些HTML获取不受信任的用户输入。
由于Bleach使用html5lib以与浏览器相同的方式解析文档片段,因此它对未知攻击具有极强的抵抗力,远远超过基于常规表达式的清洁剂。
通过这种方式,您至少可以确定您的攻击面较小,因为此软件经过了更多测试,您只需要担心允许的HTML标记,而不是代码的工作原理。
用法示例:
import bleach
mystring = bleach.clean(form.cleaned_data['mystring'],
tags=ALLOWED_TAGS,
attributes=ALLOWED_ATTRIBUTES,
styles=ALLOWED_STYLES,
strip=False, strip_comments=True)
答案 1 :(得分:1)
这可能不安全。 BeautifulSoup默认使用lxml.html解析器,并且可能会利用此浏览器和浏览器之间的差异。解析器(全部遵循HTML规范)走私浏览器将视为元素的字符串,但您的代码不会。使用带有html5lib的BeautifulSoup可以减轻可能的攻击面,因为你有一个与浏览器相同的解析器。
您可能不希望允许宽度,高度和类,因为它允许攻击者将其图像设置为整个页面大小。
总的来说,我同意Wtower的回答,即使用已建立的第三方库可能更安全。