2009-03-30 9 views
24

Quelle est la méthode recommandée pour échapper au code HTML afin d'éviter les vulnérabilités XSS dans les applications Rails?Echapper à HTML dans Rails

Si vous autorisez l'utilisateur à insérer du texte dans la base de données mais à y échapper lors de son affichage? Devriez-vous ajouter des filtres before_save pour échapper à l'entrée?

Répondre

22

Il existe trois approches de base à ce problème.

  1. utilisez h() dans vos vues. L'inconvénient ici est que si vous oubliez, vous obtenez pwnd.
  2. Utilisez un plug-in qui échappe au contenu lors de son enregistrement. Mon plugin xss_terminate fait cela. Alors vous ne devez pas utiliser h() dans votre point de vue (surtout). Il y en a d'autres qui fonctionnent au niveau du contrôleur. Les inconvénients sont les suivants: (a) s'il y a un bug dans le code d'échappement, vous pouvez obtenir XSS dans votre base de données; et (b) Il y a des cas de coin où vous voudrez toujours utiliser h().
  3. Utilisez un plug-in qui échappe au contenu lorsqu'il est affiché. CrossSiteSniper est probablement le plus connu d'entre eux. Cela alias vos attributs de sorte que lorsque vous appelez foo.name, il échappe au contenu. Il y a un moyen de contourner le problème si vous avez besoin d'un contenu non échappé. J'aime ce plugin mais je ne suis pas fou de laisser XSS dans ma base de données en premier lieu ...

Ensuite, il existe quelques approches hybrides.

Il n'y a aucune raison pour laquelle vous ne pouvez pas utiliser xss_terminate et CrossSiteSniper en même temps.

Il existe également une implémentation ERb appelée Erubis qui peut être configurée pour que tout appel tel que <%= foo.name %> soit échappé - l'équivalent de <%= h(foo.name) %>. Malheureusement, Erubis semble toujours être à la traîne derrière Rails et ainsi l'utiliser peut vous ralentir.

Si vous voulez lire plus, j'ai écrit un article de blog (que Xavor a aimablement lié à) sur using xss_terminate.

+0

Votre plugin fonctionne très bien. Merci! – djburdick

+0

Pourrait-on mettre à jour ceci pour Rails 3? – slhck

+1

Yuck. Les données échappées dans votre base de données sont une mauvaise idée pour la santé mentale. – Ashe

5

Utilisez la méthode h dans votre modèle de vue. Disons que vous avez un objet de poste avec une propriété de commentaire:

<div class="comment"> 
    <%= h post.comment %> 
</div> 
13

Le h est un alias pour html_escape, qui est une méthode utilitaire pour échapper à tous les caractères de balise HTML:

html_escape('<script src=http://ha.ckers.org/xss.js></script>') 
# => &lt;script src=http://ha.ckers.org/xss.js&gt;&lt;/script&gt; 

Si vous avez besoin de plus de contrôle, aller avec la méthode sanitize, qui peut être utilisé comme une liste blanche des balises et les attributs pour permettre:

sanitize(@article.body, :tags => %w(table tr td), :attributes => %w(id class style)) 

Je permettrait à l'utilisateur de quoi que ce soit d'entrée, la stocker en l'état dans la base de données, et d'évasion lors de l'afficher . De cette façon, vous ne perdez aucune information entrée. Vous pouvez toujours modifier la logique d'échappement plus tard ...

+0

Je seconde le mouvement de laisser les utilisateurs entrer n'importe quoi et échapper dans les affichages seulement. xss_terminate est sympa mais peut être lent et rend la mise à niveau vers Rails 3 beaucoup plus difficile. – simianarmy

0

Je viens de sortir un plugin appelé ActsAsSanitiled en utilisant la gemme Sanitize qui peut garantir une bonne forme et être très configurable à quel type de HTML est autorisé, le tout sans passer par la saisie de l'utilisateur ou nécessitant de mémoriser quelque chose au template niveau.

Questions connexes