Sanitizing entrada de utilizador usando o Python

votos
52

Qual é a melhor maneira de higienizar a entrada do usuário para um aplicativo web baseado em Python? Existe uma única função para remover caracteres HTML e quaisquer outras combinações de caracteres necessários para evitar um XSS ou ataque de injeção SQL?

Publicado 19/08/2008 em 21:18
fonte usuário
Em outras línguas...                            


7 respostas

votos
24

Aqui está um trecho que irá remover todas as tags não está na lista branca, e todos os atributos de tag não na whitelist atributos de e (assim você não pode usar onclick).

É uma versão modificada do http://www.djangosnippets.org/snippets/205/ , com a regex sobre os valores de atributos para impedir as pessoas de usar href="javascript:...", e outros casos descritos na http://ha.ckers.org/xss .html .
(por exemplo, <a href="ja&#x09;vascript:alert('hi')">ou <a href="ja vascript:alert('hi')">, etc)

Como você pode ver, ele usa o (incrível) BeautifulSoup biblioteca.

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')

Como os outros cartazes disse, praticamente todas as bibliotecas Python db cuidar de injeção de SQL, por isso deve praticamente cobertura que você.

Respondeu 24/08/2008 em 17:08
fonte usuário

votos
20

Editar : água sanitária é um invólucro em torno html5lib o que torna ainda mais fácil de usar como um desinfectante à base de whitelist.

html5libvem com um higienizador de HTML baseado em whitelist - é fácil de subclasse-lo para restringir as tags e atributos de usuários têm permissão para usar em seu site, e até mesmo tentativas de higienizar CSS se você está permitindo o uso do styleatributo.

Aqui está agora estou usando-o em meu clone Stack Overflow sanitize_htmlfunção de utilidade:

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

Eu joguei todos os ataques listados na de ha.ckers.org XSS Cheatsheet (que são convenientemente disponíveis em formato XML para ele após a realização Markdown para conversão em HTML usando python-markdown2 e parece mantiveram-se ok.

O componente de edição WMD que Stackoverflow usa atualmente é um problema, embora - Eu realmente tive que desativar o JavaScript para testar os ataques XSS Cheatsheet, como colá-los todos em WMD acabou me dando caixas de alerta e apagando a página.

Respondeu 30/10/2008 em 01:41
fonte usuário

votos
12

A melhor maneira de prevenir XSS não é tentar e filtrar tudo, mas em vez de simplesmente fazer a codificação de entidade HTML. Por exemplo, virar automaticamente <em & lt ;. Esta é a solução ideal supondo que você não precisa aceitar qualquer entrada de html (fora do fórum áreas / comentário onde é usado como marcação, que deve ser bastante raro precisa aceitar HTML); há tantas permutações via codificações alternativas que qualquer coisa, mas uma whitelist ultra-restritiva (az, AZ, 0-9, por exemplo) vai deixar algo passar.

Injeção SQL, ao contrário da outra opinião, ainda é possível, se você está apenas construindo uma cadeia de consulta. Por exemplo, se você está apenas concatenando um parâmetro de entrada em uma string de consulta, você terá SQL Injection. A melhor maneira de proteger contra isso também não é a filtragem, mas em vez de usar religiosamente consultas parametrizadas e NUNCA concatenar entrada do usuário.

Isso não quer dizer que a filtragem não é ainda uma prática recomendada, mas em termos de injeção SQL e XSS, você será muito mais protegido se você religiosamente usar parametrizar consultas e HTML Entity Encoding.

Respondeu 18/09/2008 em 16:56
fonte usuário

votos
6

-Se Jeff Atwood descreveu como StackOverflow.com sanitizes entrada do usuário (em termos específicos não-idioma) no blog Stack Overflow: http://blog.stackoverflow.com/2008/06/safe-html-and-xss/

No entanto, como Justin aponta, se você usar modelos Django ou algo similar, então eles provavelmente higienizar sua saída HTML de qualquer maneira.

injeção de SQL também não deve ser uma preocupação. Todas as bibliotecas de banco de dados do Python (MySQLdb, cx_Oracle, etc) sempre higienizar os parâmetros que você passa. Essas bibliotecas são usadas por todos os mapeadores objeto-relacional do Python (tais como modelos do Django), assim você não precisa se preocupar com o saneamento lá.

Respondeu 19/08/2008 em 21:51
fonte usuário

votos
4

Eu não faço desenvolvimento web muito mais tempo, mas quando eu fiz, eu fiz algo assim:

Quando nenhuma análise é suposto acontecer, eu geralmente apenas escapar os dados para não interferir com o banco de dados quando eu armazená-lo e escapar tudo o que li a partir do banco de dados a não interferir com html quando eu exibi-lo (cgi.escape () in python).

As possibilidades são, se alguém tentasse caracteres HTML de entrada ou coisas, eles realmente queriam que a ser exibido como texto de qualquer maneira. Se não o fizessem, bem difícil :)

Em suma sempre escapar o que pode afetar o alvo atual para os dados.

Quando eu fiz precisa de alguma análise (markup ou qualquer outro) eu costumo tentei manter essa língua de uma forma não-interseção definida com html para que eu pudesse ainda apenas armazená-lo adequadamente escape (após validar erros de sintaxe) e analisá-lo para html ao exibir sem ter que se preocupar com os dados que o usuário colocar lá interferir com o seu html.

Veja também Escapando HTML

Respondeu 24/08/2008 em 17:23
fonte usuário

votos
2

Para esterilizar a entrada de string que você deseja armazenar no banco de dados (por exemplo, um nome do cliente), você precisa ou para escapar ou simplesmente remover quaisquer aspas (' ") a partir dele. Isto impede eficazmente injeção SQL clássica que pode acontecer se você está montando uma consulta SQL a partir de seqüências passadas pelo usuário.

Por exemplo (se é aceitável para remover citações completamente):

datasetName = datasetName.replace("'","").replace('"',"")
Respondeu 01/10/2009 em 13:21
fonte usuário

votos
0

Se você estiver usando uma estrutura como Django , o quadro pode facilmente fazer isso para você, utilizando filtros padrão. Na verdade, eu tenho certeza que o Django faz isso automaticamente, a menos que você diga a ele para não.

Caso contrário, eu recomendo usar algum tipo de validação regex antes de aceitar entradas de formulários. Eu não acho que há uma bala de prata para o seu problema, mas usando o módulo re, você deve ser capaz de construir o que você precisa.

Respondeu 19/08/2008 em 21:24
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more