首页 文章

使用Python消除用户输入

提问于
浏览
56

清理基于Python的Web应用程序的用户输入的最佳方法是什么?是否有一个函数可以删除HTML字符和任何其他必要的字符组合,以防止XSS或SQL注入攻击?

7 回答

  • 6

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

    它是http://www.djangosnippets.org/snippets/205/的修改版本,在属性值上使用正则表达式来阻止人们使用 href="javascript:..." ,以及http://ha.ckers.org/xss.html中描述的其他情况 .
    (例如 <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数据库都会处理SQL注入,因此这应该会覆盖你 .

  • 2

    Editbleach是html5lib的包装器,它使得它更容易用作基于白名单的杀菌器 .

    html5lib附带基于白名单的HTML清除程序 - 它允许使用 style 属性 .

    这里's now I'm在我的Stack Overflow clone的 sanitize_html 实用程序函数中使用它:

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

    我已经抛出了ha.ckers.org's XSS Cheatsheet中列出的所有攻击(在使用python-markdown2执行Markdown到HTML转换之后很容易available in XML format,它似乎已经保持正常 .

    Stackoverflow目前使用的WMD编辑器组件是一个问题,但实际上我必须禁用JavaScript以测试XSS Cheatsheet攻击,因为将它们全部粘贴到WMD中最终会给我提醒警告框并消隐页面 .

  • 12

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

    如果您只是构建一个查询字符串,SQL注入与其他观点相反仍然是可能的 . 例如,如果您只是将传入参数连接到查询字符串,那么您将拥有SQL注入 . 防止这种情况的最佳方法也不是过滤,而是虔诚地使用参数化查询并且永远不会连接用户输入 .

    这并不是说过滤仍然不是最佳实践,但就SQL注入和XSS而言,如果您虔诚地使用参数化查询和HTML实体编码,您将受到更多保护 .

  • 4

    Jeff Atwood自己描述了StackOverflow.com如何在Stack Overflow博客上清理用户输入(以非语言特定的术语):http://blog.stackoverflow.com/2008/06/safe-html-and-xss/

    但是,正如Justin指出的那样,如果您使用Django模板或类似的东西,那么他们可能无论如何都要清理您的HTML输出 .

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

  • 26

    我不再进行Web开发,但是当我这样做时,我做了类似的事情:

    当没有解析应该发生时,我通常只是逃避数据,以便在我存储数据时不干扰数据库,并且从数据库中读取所有内容,以便在显示时不干扰html(cgi.escape()in蟒蛇) .

    有可能,如果有人试图输入html字符或东西,他们实际上希望无论如何都要显示为文本 . 如果他们没有,那就太难了:)

    总之,总是逃避可能影响当前数据目标的东西 .

    当我确实需要一些解析(标记或其他)时,我通常会尝试将该语言保存在与html不相交的集合中,因此我仍然可以将其存储为适当的转义(在验证语法错误之后)并在显示时将其解析为html不得不担心用户放在那里干扰你的HTML的数据 .

    另见Escaping HTML

  • 20

    要清理要存储到数据库的字符串输入(例如客户名称),您需要将其转义或从中明确删除任何引号(',“) . 这有效地防止了经典的SQL注入,如果您正在从用户传递的字符串中组装SQL查询 .

    例如(如果可以完全删除引号):

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

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

    否则,我建议在接受表单输入之前使用某种正则表达式验证 . 我不认为你的问题有灵丹妙药,但使用re模块,你应该能够构建你需要的东西 .

相关问题