2008-08-19 91 views
51

清理基于Python的Web应用程序的用户输入的最佳方式是什么?是否有单一功能来删除HTML字符和任何其他必要的字符组合以防止发生XSS或SQL注入攻击?使用Python清理用户输入

+9

你不应该试图通过消毒来解决SQL注入用户输入!如果数据库API正确使用,则不会有SQL注入的机会。 – 2010-03-22 20:52:57

+2

`...如果使用数据库API恰当的是没有SQL注入的机会。正确地说,你的意思是使用参数化查询吗?这是否覆盖你100%? – Medorator 2014-08-27 15:03:36

+2

@buffer,我知道你的评论是旧的,但如果你想让除OP之外的其他人看到你的评论,你必须用\ @符号将它们打出来。 – user1717828 2015-10-27 19:59:07

回答

0

如果您使用像django这样的框架,该框架可以轻松地为您使用标准过滤器执行此操作。事实上,我很确定django会自动执行它,除非您告诉它不要。

否则,我会建议在接受来自表单的输入之前使用某种正则表达式验证。我不认为你的问题有一个银弹,但使用重新模块,你应该能够构建你所需要的。

6

杰夫阿特伍德自己形容StackOverflow.com如何进行消毒的堆栈溢出博客用户输入(在非语言的具体条款):http://blog.stackoverflow.com/2008/06/safe-html-and-xss/

然而,贾斯汀指出,如果你使用Django模板或类似的东西那么他们可能会净化你的HTML输出。

SQL注入也不应该是一个问题。所有Python的数据库库(MySQLdb,cx_Oracle等)都会清理你传递的参数。 Python的所有对象关系映射器(如Django模型)都使用这些库,因此您不必担心那里的卫生设施。

24

这是一个片段,它将删除所有不在白名单上的标签,并且所有标签属性都不在白名单上(因此您不能使用onclick)。

这是http://www.djangosnippets.org/snippets/205/的改良版,与http://ha.ckers.org/xss.html描述的属性值的正则表达式,以防止有人利用href="javascript:...",和其他案件。
(例如<a href="ja&#x09;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注入的,所以这应该非常盖你。

+2

我提高了这一点,但现在我不太确定。我不认为这可以保护IE用户免受src =“vbscript:msgbox('xss')”的攻击。 – 2010-03-22 18:30:06

4

我不这样做Web开发多不再,但是当我做,我做了一件像这样:

当没有解析是应该发生的,我通常只是逃避数据不与数据库干扰当我存储它,并逃离从数据库中读取的所有内容,以便在显示它时不干扰html(在python中使用cgi.escape())。

有可能是,如果有人试图输入html字符或东西,他们实际上希望它被显示为文本。如果他们没有,好困难:)

总之逃避什么会影响当前目标的数据。

当我确实需要一些解析(标记或其他)时,我通常试图用html保持该语言不交叉集合,所以我仍然可以适当地将它存储(在验证语法错误后)并解析它HTML时显示,而不必担心用户放在那里干扰你的HTML数据。

Escaping HTML

12

见防止XSS不是要设法和过滤一切的最好方式,而是简单地做HTML实体编码。例如,自动将<转换为& lt ;.这是理想的解决方案,假设您不需要接受任何html输入(在用作标记的论坛/评论区域之外,需要接受HTML应该很少见)。通过替代编码有如此多的排列,除了超限制的白名单(例如a-z,A-Z,0-9)之外的任何东西都会让某些东西通过。

如果您只是构建查询字符串,则与其他意见相反,SQL注入仍是可能的。例如,如果您只是将传入参数连接到查询字符串,则您将拥有SQL注入。防止出现这种情况的最好方法也不是过滤,而是虔诚地使用参数化查询,而不是连接用户输入。

这并不是说过滤仍不是最佳实践,但就SQL注入和XSS而言,如果您宗教上使用参数化查询和HTML实体编码,将会受到更多的保护。

19

编辑bleach是html5lib的一个包装,使它更容易用作基于白名单的sanitiser。

html5lib附带基于白名单的HTML sanitiser - 很容易将其子类化,以限制用户可以在您的网站上使用的标签和属性,甚至可以尝试清理CSS,如果您允许使用style属性。

这里的现在,我使用它在我堆栈溢出的克隆的sanitize_html效用函数:

http://code.google.com/p/soclone/source/browse/trunk/soclone/utils/html.py

我已经抛出(在ha.ckers.org's XSS Cheatsheet列出的所有攻击,这是在执行降价后的它轻而易举地available in XML format HTML转换使用python-markdown2并且它似乎保持不变

虽然Stackoverflow当前使用的WMD编辑器组件是一个问题,但实际上我不得不禁用JavaScript来测试XS S Cheatsheet攻击将它们全部粘贴到WMD中,最终给了我警戒框并清空了页面。

2

要清理要存储到数据库的字符串输入(例如客户名称),您需要将其转义或明显地从中删除引号(',“)。如果你正在组装从用户传递的字符串的SQL查询可以发生

例如(如果它是可以接受的完全删除引号):

datasetName = datasetName.replace("'","").replace('"',"")