Desinfiserende brukerinngang ved hjelp av Python

stemmer
55

Hva er den beste måten å rense brukerundersøkelser for en Python-basert web-applikasjon? Er det en enkel funksjon for å fjerne HTML-tegn og eventuelle andre nødvendige tegn kombinasjoner for å hindre en XSS eller SQL-injeksjon angrep?

Publisert på 19/08/2008 klokken 20:18
kilden bruker
På andre språk...                            


7 svar

stemmer
26

Her er et tekstutdrag som vil fjerne alle tagger ikke på den hvite listen, og alle kodeattributter ikke på attribues hviteliste (slik at du ikke kan bruke onclick).

Det er en modifisert versjon av http://www.djangosnippets.org/snippets/205/ , med regex på attributtverdiene for å hindre folk fra å bruke href="javascript:...", og andre tilfeller beskrevet på http://ha.ckers.org/xss .html .
(f.eks <a href="ja&#x09;vascript:alert('hi')">eller <a href="ja vascript:alert('hi')">, etc.)

Som du kan se, bruker den (utrolig) BeautifulSoup biblioteket.

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

Som andre plakater har sagt, ganske mye alle Python db biblioteker ta vare på SQL-injeksjon, så dette bør ganske mye dekke deg.

Svarte 24/08/2008 kl. 16:08
kilden bruker

stemmer
20

Edit : blekemiddel er en wrapper rundt html5lib som gjør det enda enklere å bruke som en hviteliste basert sanitiser.

html5libkommer med en hviteliste-baserte HTML sanitiser - det er lett å underklasse det å begrense kodene og attributter brukere har lov til å bruke på nettstedet ditt, og det til og med forsøker å rense CSS hvis du tillater bruk av styleattributtet.

Her er nå er jeg bruke det i min Stack Overflow klone sin sanitize_htmlnyttefunksjon:

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

Jeg har kastet alle angrepene er oppført i ha.ckers.org XSS Cheatsheet (som er enkelt og greit tilgjengelig i XML-format på det etter å ha utført Markdown til HTML konvertering ved hjelp av python-markdown2 og det synes å ha holdt opp ok.

WMD redaktør komponent som Stackoverflow benytter i dag er et problem, selv om - jeg hadde egentlig å deaktivere Javascript for å teste XSS cheatsheet angrep, så lime dem inn WMD endte opp med å gi meg varsling bokser og blanking ut på siden.

Svarte 30/10/2008 kl. 00:41
kilden bruker

stemmer
12

Den beste måten å forhindre XSS er ikke å forsøke å filtrere alt, men heller å bare gjøre HTML Entity koding. For eksempel, automatisk slå <i & lt ;. Dette er den ideelle løsningen forutsatt at du ikke trenger å godta noen html-inngang (utenfor forum / kommentar områder hvor det er brukt som markering, det skal være ganske sjelden å trenge å godta HTML); det er så mange permutasjoner via alternative kodinger som alt annet enn en ultra-restriktiv hviteliste (az, AZ, 0-9 for eksempel) kommer til å la noe gjennom.

SQL Injection, i motsetning til annen oppfatning, er fortsatt mulig, hvis du bare bygge ut en spørrestreng. For eksempel, hvis du bare sette sammen en innkommende parameter på en spørrestreng, vil du ha SQL Injection. Den beste måten å beskytte mot dette er heller ikke filtrering, men heller å religiøst bruke parametriserte spørsmål og ALDRI sette sammen brukerundersøkelser.

Dette er ikke å si at filtrering er ikke fortsatt en beste praksis, men i form av SQL Injection og XSS, vil du være langt mer beskyttet hvis du religiøst bruke parameterspørringer og HTML Entity koding.

Svarte 18/09/2008 kl. 15:56
kilden bruker

stemmer
6

Jeff Atwood selv beskrev hvordan StackOverflow.com sanitizes brukerundersøkelser (i ikke-språk-spesifikke vilkår) på Stack Overflow bloggen: http://blog.stackoverflow.com/2008/06/safe-html-and-xss/

Men som Justin påpeker, hvis du bruker Django maler eller noe lignende da de sannsynligvis rense HTML utgang uansett.

SQL-injeksjon også bør ikke være en bekymring. Alle Pythons database biblioteker (MySQLdb, cx_Oracle, etc) alltid rense parametrene du passerer. Disse bibliotekene blir brukt av alle Pythons objektrelasjons kartleggere (som Django modeller), så du trenger ikke å bekymre deg for sanitær der heller.

Svarte 19/08/2008 kl. 20:51
kilden bruker

stemmer
4

Jeg kan ikke gjøre webutvikling mye lenger, men når jeg gjorde det, jeg gjorde noe sånt som dette:

Når ingen parsing er ment å skje, jeg vanligvis bare flykte dataene til å ikke forstyrre databasen når jeg lagre det, og slippe alt jeg leste opp fra databasen til å ikke forstyrre html når jeg vise det (cgi.escape () i python).

Sjansene er, hvis noen prøvde å legge inn html tegn eller ting, de faktisk ønsket at skal vises som tekst uansett. Hvis de ikke gjorde det, vel tøft :)

Kort sagt alltid unnslippe hva som kan påvirke nåværende mål for dataene.

Da jeg trengte noen parsing (markup eller hva) jeg vanligvis forsøkt å holde dette språket i en ikke-kryssende sett med html så jeg kunne fortsatt bare lagre den passende rømt (etter validering for syntaksfeil) og analysere det til html ved visning uten å måtte bekymre seg om dataene brukeren satt der i konflikt med html.

Se også Rømmer HTML

Svarte 24/08/2008 kl. 16:23
kilden bruker

stemmer
2

Å rense en streng inngang som du vil lagre i databasen (for eksempel et kundenavn) du trenger enten å unnslippe det eller tydelig fjerne eventuelle sitater (' ") fra den. Dette forhindrer effektivt klassisk SQL-injeksjon som kan skje hvis du installasjon av en SQL-spørring fra strenger vedtatt av brukeren.

For eksempel (hvis det er akseptabelt å fjerne sitater fullstendig):

datasetName = datasetName.replace("'","").replace('"',"")
Svarte 01/10/2009 kl. 12:21
kilden bruker

stemmer
0

Hvis du bruker et rammeverk som Django , kan rammen enkelt gjøre dette for deg ved hjelp av vanlige filtre. Faktisk er jeg ganske sikker på at django automatisk gjør det med mindre du forteller det ikke til.

Ellers vil jeg anbefale å bruke noen form for regex validering før den godtar innspill fra skjemaer. Jeg tror ikke det er en sølvkule for ditt problem, men ved hjelp av re-modulen, bør du være i stand til å konstruere det du trenger.

Svarte 19/08/2008 kl. 20:24
kilden bruker

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