Quelle est la meilleure façon d'assainir les entrées utilisateur pour une application Web basée sur Python? Y a-t-il une seule fonction pour supprimer les caractères HTML et toute autre combinaison de caractères nécessaires pour empêcher une attaque par injection XSS ou SQL?Désinfection de l'entrée utilisateur à l'aide de Python
Répondre
Si vous utilisez un framework tel que django, le framework peut facilement le faire pour vous en utilisant des filtres standard. En fait, je suis sûr que django le fait automatiquement à moins que vous le lui disiez. Sinon, je recommanderais d'utiliser une sorte de validation regex avant d'accepter les entrées des formulaires. Je ne pense pas qu'il y ait une solution miracle à votre problème, mais en utilisant le module re, vous devriez être capable de construire ce dont vous avez besoin.
Jeff Atwood lui-même décrit comment StackOverflow.com aseptise entrée utilisateur (en termes non spécifiques à une langue) sur le blog Stack Overflow: http://blog.stackoverflow.com/2008/06/safe-html-and-xss/
Cependant, comme le souligne Justin sur, si vous utilisez des modèles Django ou quelque chose de similaire alors ils ont probablement désinfecté votre sortie HTML de toute façon.
L'injection SQL ne devrait pas être un problème. Toutes les bibliothèques de bases de données de Python (MySQLdb, cx_Oracle, etc.) nettoient toujours les paramètres que vous passez. Ces bibliothèques sont utilisées par tous les mappeurs relationnels objet de Python (tels que les modèles Django), vous n'avez donc pas besoin de vous soucier de l'assainissement.
Voici un extrait qui supprimera toutes les balises ne figurant pas dans la liste blanche et tous les attributs de balises qui ne figurent pas dans la liste blanche des attributions (vous ne pouvez donc pas utiliser onclick
).
Il est une version modifiée de http://www.djangosnippets.org/snippets/205/, avec l'expression régulière sur les valeurs d'attribut pour empêcher les gens d'utiliser href="javascript:..."
, et d'autres cas décrits à http://ha.ckers.org/xss.html.
(par exemple <a href="ja	vascript:alert('hi')">
ou <a href="ja vascript:alert('hi')">
, etc.)
Comme vous pouvez le voir, il utilise le (génial) bibliothèque 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')
Comme l'ont dit les autres affiches, à peu près toutes les bibliothèques db Python prendre soin d'injection SQL, cette couverture devrait à peu près vous.
Je l'ai mis à jour, mais maintenant je ne suis pas si sûr. Je ne pense pas que cela protège les utilisateurs IE contre les attaques src = "vbscript: msgbox ('xss')". –
Vous pourriez facilement ajouter cela avec une autre regex pour vbscript: comme celle pour javascript: – tghw
Protection VBScript ajoutée. – tghw
Je ne fais pas le développement web beaucoup plus longtemps, mais quand je l'ai fait, je l'ai fait quelque chose comme ceci:
Lorsqu'aucun analyse syntaxique est censé se produire, je me sauve plus souvent que les données pour ne pas interférer avec la base de données quand je le stocke, et que j'échappe à tout ce que je lis de la base de données pour ne pas interférer avec html quand je l'affiche (cgi.escape() en python).
Les chances sont, si quelqu'un a essayé d'entrer des caractères html ou des choses, ils voulaient réellement que cela soit affiché comme texte de toute façon. Si ce n'est pas le cas, bien difficile :)
En bref, toujours échapper ce qui peut affecter la cible actuelle pour les données. Quand j'avais besoin d'un peu d'analyse (balisage ou autre), j'essayais habituellement de garder ce langage dans un ensemble sans intersection avec html afin que je puisse toujours le stocker correctement échappé (après validation pour les erreurs de syntaxe) et l'analyser html lors de l'affichage sans avoir à se soucier des données que l'utilisateur met en interférant avec votre code html.
Voir aussi Escaping HTML
La meilleure façon d'éviter XSS est de ne pas essayer de tout filtrer, mais plutôt de faire simplement le codage HTML entité. Par exemple, tournez automatiquement < en & lt ;. C'est la solution idéale en supposant que vous n'avez pas besoin d'accepter une entrée html (en dehors des zones de forum/commentaire où il est utilisé comme balisage, il devrait être assez rare d'avoir besoin d'accepter du HTML); il y a tellement de permutations via des encodages alternatifs que tout sauf une liste blanche ultra-restrictive (a-z, A-Z, 0-9 par exemple) va laisser passer quelque chose.
Injection SQL, contrairement à d'autres avis, est toujours possible, si vous construisez simplement une chaîne de requête. Par exemple, si vous ne faites que concaténer un paramètre entrant sur une chaîne de requête, vous aurez l'injection SQL. La meilleure façon de se protéger contre cela est également de ne pas filtrer, mais plutôt d'utiliser religieusement des requêtes paramétrées et JAMAIS concaténer les entrées des utilisateurs. Cela ne veut pas dire que le filtrage n'est pas toujours une bonne pratique, mais en termes d'injection SQL et XSS, vous serez bien plus protégé si vous utilisez religieusement les requêtes Parameterize et le codage d'entité HTML.
Ce n'est pas correct dans de nombreux cas. Voir les notes OSWAP sur "Pourquoi est-ce que je ne peux pas simplement Entité HTML Encoder des données non fiables?" https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet – Purrell
Modifier: bleach est un wrapper autour de html5lib qui le rend encore plus facile à utiliser en tant que désinfectant à base de liste blanche.
html5lib
est livré avec un basé whitelist HTML assainissant - il est facile de sous-classe pour limiter les balises et les attributs utilisateurs sont autorisés à utiliser sur votre site, et il essaie même de désinfectez CSS si vous permettant d'utiliser la style
attribut.
est ici maintenant je l'utilise dans mon fonction d'utilité de clone Stack Overflow sanitize_html
:
http://code.google.com/p/soclone/source/browse/trunk/soclone/utils/html.py
J'ai jeté toutes les attaques énumérées dans ha.ckers.org's XSS Cheatsheet (qui haut la main available in XML format à elle après avoir effectué Markdown à La conversion HTML en utilisant python-markdown2 et il semble avoir tenu bon
Le composant éditeur WMD que Stackoverflow utilise actuellement est un problème, cependant - J'ai dû désactiver JavaScript pour tester le XS S attaques Cheatsheet, comme les coller tous dans WMD a fini par me donner des boîtes d'alerte et de masquer la page.
Pour désinfecter une entrée de chaîne que vous souhaitez stocker dans la base de données (par exemple, un nom de client), vous devez soit y échapper, soit supprimer les guillemets (','). peut se produire si vous assemblez une requête SQL de chaînes transmises par l'utilisateur
par exemple (s'il est acceptable de supprimer les citations complètement).
datasetName = datasetName.replace("'","").replace('"',"")
Euh ... non ... Je ne le ferais toujours pas. Pour tout ce qui est un élément de données, utilisez des requêtes paramétrées. Pour les non-données (requêtes créées dynamiquement), vous devriez vraiment utiliser une liste blanche. 'pg_catalog.pg_user' ne contient pas de guillemets, mais vous ne le souhaitez probablement pas dans vos requêtes générées. Au lieu de cela, faites quelque chose comme 'datasetName = datasetName si datasetName dans DATASETNAME_WHITELIST sinon sulk()' – SingleNegationElimination
- 1. asp.net désinfection de l'entrée utilisateur
- 2. Filtrage/Désinfection de l'entrée utilisateur. Meilleure approche
- 3. structure de données laide à la recherche java
- 4. Désinfection SQL VBScript
- 5. Désinfection des données de l'enregistrement actif
- 6. Désinfection de XML incorrect en Java
- 7. Désinfection des données en PHP
- 8. Désinfection du flux KML pour modifier l'espace de noms xml
- 9. Rediriger 301 Le transfert vers l'URL de sortie du nouveau domaine est laide
- 10. Stockez les paramètres utilisateur simples en Python
- 11. Recadrer l'image à partir de l'entrée utilisateur
- 12. Détection de l'inactivité à l'aide de Python
- 13. Bibliothèques C++ SQL Sanitization ou constructeurs de requêtes offrant la désinfection
- 14. Application de chat web d'utilisateur à utilisateur (PHP) - quel choix?
- 15. Comment associer mon utilisateur de l'application facebook à mon utilisateur de l'application Web?
- 16. Comment ajouter un utilisateur à AD à l'aide de System.DirectoryServices.AccountManagement?
- 17. bonne pratique pour les préférences utilisateur dans $ HOME en Python
- 18. python méthode de mise à jour dictionnaire
- 19. Python construction de fonctions à la volée
- 20. Ajout d'un alias de codage à python
- 21. Groovy équivalent à l'instruction exec de Python?
- 22. lancer VS2008 construire à partir de python
- 23. code python de port à javascript
- 24. Scripting LMMS à partir de Python
- 25. Appelez Python à partir de C++
- 26. déclaration de mise à jour Python MYSQL
- 27. Écriture de XML à partir de Python: équivalent Python de .NET XmlTextWriter?
- 28. utilisateur apache ne peut pas écrire .python-oeufs
- 29. Division de la sortie de ps à l'aide de Python
- 30. Boîte de message en Python
vous ne devriez pas tenter de fixer l'injection SQL par désinfectante Si l'API de la base de données est utilisée correctement, il n'y a aucune chance d'injection SQL –
'... si l'API de base de données est utilisée correctement, il n'y a aucune chance d'injection SQL ». Par correctement, voulez-vous dire utiliser des requêtes paramétrées? Cela vous couvre-t-il à 100%? – Medorator
@buffer, je sais que votre commentaire est ancien, mais si vous voulez que d'autres personnes que OP voient vos commentaires, vous devez les appeler avec un symbole \ @. – user1717828