为基于Python的web应用程序清理用户输入的最佳方式是什么?是否有一个单独的函数可以删除HTML字符和任何其他必要的字符组合,以防止XSS或SQL注入攻击?
发布于 2008-08-24 16:08:38
下面这段代码将删除不在白名单上的所有标签,以及不在属性白名单上的所有标签属性(所以你不能使用onclick
)。
它是http://www.djangosnippets.org/snippets/205/的修改版本,在属性值上使用正则表达式以防止人们使用href="javascript:..."
,以及http://ha.ckers.org/xss.html中描述的其他情况。
(例如<a href="ja	vascript:alert('hi')">
或<a href="ja vascript:alert('hi')">
等)
正如您所看到的,它使用了(很棒的) BeautifulSoup库。
import re
from urlparse import urljoin
from BeautifulSoup import BeautifulSoup, Comment
def sanitizeHtml(value, base_url=None):
rjs = r'[\s]*(&#x.{1,7})?'.join(list('javascript:'))
rvb = r'[\s]*(&#x.{1,7})?'.join(list('vbscript:'))
re_scripts = re.compile('(%s)|(%s)' % (rjs, rvb), re.IGNORECASE)
validTags = 'p i strong b u a h1 h2 h3 pre br img'.split()
validAttrs = 'href src width height'.split()
urlAttrs = 'href src'.split() # Attributes which should have a URL
soup = BeautifulSoup(value)
for comment in soup.findAll(text=lambda text: isinstance(text, Comment)):
# Get rid of comments
comment.extract()
for tag in soup.findAll(True):
if tag.name not in validTags:
tag.hidden = True
attrs = tag.attrs
tag.attrs = []
for attr, val in attrs:
if attr in validAttrs:
val = re_scripts.sub('', val) # Remove scripts (vbs & js)
if attr in urlAttrs:
val = urljoin(base_url, val) # Calculate the absolute url
tag.attrs.append((attr, val))
return soup.renderContents().decode('utf8')
正如其他发帖者所说,几乎所有的Python db库都负责SQL注入,因此这篇文章应该涵盖了您的大部分内容。
发布于 2008-09-18 15:56:10
防止XSS的最好方法不是尝试过滤所有内容,而是简单地进行HTML实体编码。例如,自动将<转换为<。这是一个理想的解决方案,假设您不需要接受任何html输入(在论坛/评论区之外,它被用作标记,几乎不需要接受HTML);通过替代编码有如此多的排列,除了极端限制性的白名单(例如,a-z,A-Z,0-9 )之外,任何东西都会让一些东西通过。
与其他观点相反,如果您只是构建一个查询字符串,SQL注入仍然是可能的。例如,如果您只是将传入参数连接到查询字符串上,则会有SQL注入。防止这种情况的最好方法也不是过滤,而是严格使用参数化查询,永远不要连接用户输入。
这并不是说过滤不再是最佳实践,但就SQL注入和XSS而言,如果您认真使用参数化查询和HTML实体编码,您将受到更多的保护。
发布于 2008-08-19 20:51:40
Jeff Atwood本人在Stack Overflow博客上描述了StackOverflow.com如何清理用户输入(使用非特定语言的术语):https://blog.stackoverflow.com/2008/06/safe-html-and-xss/
然而,正如Justin指出的那样,如果您使用Django模板或类似的东西,那么它们可能无论如何都会清理您的HTML输出。
SQL注入也不应该是一个问题。Python的所有数据库库(MySQLdb、cx_Oracle等)总是清理您传递的参数。所有Python的对象关系映射器(比如Django模型)都使用这些库,因此您也不必担心那里的卫生问题。
https://stackoverflow.com/questions/16861
复制相似问题