<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.menfin.info/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>M'enfin ?!? - Rails</title>
  <link>http://blog.menfin.info/</link>
  <description></description>
  <language>fr</language>
  <pubDate>Mon, 18 Aug 2008 22:16:07 +0200</pubDate>
  <copyright></copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Rails et la sécurité</title>
    <link>http://blog.menfin.info/post/2008/07/18/Rails-et-la-securite</link>
    <guid isPermaLink="false">urn:md5:f46329425400828340823ebc7244d49a</guid>
    <pubDate>Fri, 18 Jul 2008 23:45:00 +0200</pubDate>
    <dc:creator>M'enfin ?!?</dc:creator>
        <category>Rails</category>
            
    <description>    &lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;La sécurité des applications web est souvent un sujet délicat : peu de
temps à y consacrer, mais cela peut avoir des conséquences assez graves. Pas de
panique ! &lt;a href=&quot;http://rubyonrails.com&quot;&gt;Ruby on Rails&lt;/a&gt; est bien armé
et avec un peu de rigueur, on peut se protéger sans trop de difficultés. Nous
allons voir les principaux types d'attaques et comment les éviter.&lt;/p&gt;
&lt;h4&gt;Injections SQL&lt;/h4&gt;
&lt;p&gt;Commençons par un grand classique : &lt;a href=&quot;http://fr.wikipedia.org/wiki/Injection_SQL&quot;&gt;les injections SQL&lt;/a&gt;. Une
injection SQL consiste simplement à envoyer des données non prévues dans une
requête SQL. Prenons comme exemple une application web où les utilisateurs sont
authentifiés de la manière suivante :&lt;/p&gt;
&lt;pre&gt;
@current_user = User.find(:first, :conditions =&amp;gt; &amp;quot;login='#{params[:login]}' AND password='#{params[:password]}'&amp;quot;)
&lt;/pre&gt;
&lt;p&gt;En temps normal, quand Joe s'authentifie, la requête SQL suivante est
exécutée :&lt;/p&gt;
&lt;pre&gt;
SELECT * FROM users WHERE login='Joe' AND password='0521bc575b0ff61daa62494c7ae9c5b6' LIMIT 1;
&lt;/pre&gt;
&lt;p&gt;Mais supposons maintenant que Kevin, un Script Kiddie, passe dans le coin et
décide de mettre &lt;code&gt;&amp;quot;Joe'; --&amp;quot;&lt;/code&gt; dans le champ login. La requête SQL va
alors ressembler à :&lt;/p&gt;
&lt;pre&gt;
SELECT * FROM users WHERE login='Joe'; --' AND password='00000000000000000000000000000000' LIMIT 1;
&lt;/pre&gt;
&lt;p&gt;Kevin a réussi à se faire passer pour Joe sans connaître son mot de
passe !&lt;/p&gt;
&lt;p&gt;Heureusement, Active Record permet de &lt;a href=&quot;http://manuals.rubyonrails.com/read/chapter/43&quot;&gt;nous en protéger assez
facilement&lt;/a&gt;. Pour cela, il suffit d'utiliser les formes échappées comme
cela :&lt;/p&gt;
&lt;pre&gt;
@current_user = User.find(:first, :conditions =&amp;gt; [&amp;quot;login=? AND password=?&amp;quot;, params[:login], params[:password]])
&lt;/pre&gt;
&lt;p&gt;ou de façon équivalente :&lt;/p&gt;
&lt;pre&gt;
@current_user = User.find(:first, :conditions =&amp;gt; {:login =&amp;gt; params[:login], :password =&amp;gt; params[:password]})
&lt;/pre&gt;
&lt;p&gt;Dans les 2 cas, Active Record rajoutera un caractère &lt;code&gt;'\'&lt;/code&gt; devant
chaque apostrophe de façon à éviter les injections SQL.&lt;/p&gt;
&lt;h4&gt;L'authentification et la gestion des droits&lt;/h4&gt;
&lt;p&gt;Pour la grande majorité des projets, l'authentification (et la gestion des
droits qui vont avec) est un passage obligé. Pour cela, il existe un certain
nombre de points importants à respecter comme le chiffrement des mots de passe
stockés en base de données (ce que nous n'avons pas fait dans l'exemple
précédent). Les erreurs sont vite arrivées, aussi je vous recommande d'utiliser
des plugins reconnus comme &lt;a href=&quot;http://agilewebdevelopment.com/plugins/restful_authentication&quot;&gt;Restful
Authentication&lt;/a&gt;, &lt;a href=&quot;http://agilewebdevelopment.com/plugins/openidauthentication&quot;&gt;OpenID
Authentication&lt;/a&gt; et &lt;a href=&quot;http://www.writertopia.com/developers/authorization&quot;&gt;Authorization&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Il ne vous reste plus qu'à faire attention à un dernier détail : mettre
en cache des pages nécessitant une authentification est une mauvaise idée. En
effet, ces pages vont alors être servies par le serveur web sans passer Rails,
et donc sans vérification de l'authentification.&lt;/p&gt;
&lt;h4&gt;Se protéger des données forgées&lt;/h4&gt;
&lt;p&gt;L'étape suivante consiste à bien sécuriser l'accès aux données, aussi bien
en lecture qu'en écriture. En effet, Rails possède quelques raccourcis très
pratiques, mais qui peuvent poser problème quand ils sont mal maîtrisés. Le
plus courant est &lt;a href=&quot;http://manuals.rubyonrails.com/read/chapter/47&quot;&gt;l'affectation de masse&lt;/a&gt;,
technique qui consiste à créer un objet Active Record directement depuis les
paramètres de la requête HTTP. Par exemple, la création d'un compte utilisateur
pourra s'effectuer de la façon suivante :&lt;/p&gt;
&lt;pre&gt;
@user = User.create(params[:user])
&lt;/pre&gt;
&lt;p&gt;Supposons maintenant que la table &lt;code&gt;'users'&lt;/code&gt; comporte un champ
&lt;code&gt;'admin'&lt;/code&gt; qui vaut &lt;code&gt;0&lt;/code&gt; par défaut ou &lt;code&gt;1&lt;/code&gt; pour
les super-utilisateurs. Un utilisateur malveillant pourrait forger la requête
HTTP pour ajouter un paramètre &lt;code&gt;user&lt;a href=&quot;http://blog.menfin.info/post/2008/07/18/admin&quot; title=&quot;admin&quot;&gt;admin&lt;/a&gt;=1&lt;/code&gt; afin de gagner les pouvoirs réservés aux admins. La
première solution pour se protéger de cette attaque consiste à écrire
explicitement quels sont les paramètres autorisés :&lt;/p&gt;
&lt;pre&gt;
@user = User.create(
        :login =&amp;gt; params[:user][:login],
        :email =&amp;gt; params[:user][:email],
        :password =&amp;gt; params[:user][:password],
        :cgu =&amp;gt; params[:user][:cgu])
&lt;/pre&gt;
&lt;p&gt;Mais ceci peut vite devenir pénible quand on commence à avoir des
formulaires un peu conséquents. C'est pourquoi on lui préfère généralement la
deuxième solution : la déclaration dans le modèle de la liste des
attributs qui ne peuvent pas être modifiés. Cette déclaration se fait à l'aide
de la méthode &lt;strong&gt;&lt;code&gt;attr_protected&lt;/code&gt;&lt;/strong&gt; comme
suit :&lt;/p&gt;
&lt;pre&gt;
class User &amp;lt; ActiveRecord::Base
        attr_protected :admin
        ...
end
&lt;/pre&gt;
&lt;p&gt;Nous pouvons de nouveau utiliser l'affectation de masse sans craindre qu'un
utilisateur se fasse passer pour un admin, Rails s'occupe de filtrer les
paramètres.&lt;/p&gt;
&lt;p&gt;Dans le même style, un attaquant peut essayer de &lt;a href=&quot;http://www.therailsway.com/2007/3/26/association-proxies-are-your-friend&quot;&gt;forger
des URL&lt;/a&gt;. Si, par exemple, l'utilisateur authentifié peut supprimer l'item
n°123 qui lui appartient, en appelant l'URL &lt;code&gt;/items/delete/123&lt;/code&gt;,
alors que se passera-t-il s'il appelle la même URL pour l'item n°456 qui ne lui
appartient pas ? La réponse dépend du code de la méthode
&lt;code&gt;delete&lt;/code&gt;. Une implémentation de base pourrait ressembler
à :&lt;/p&gt;
&lt;pre&gt;
class ItemsController &amp;lt; ApplicationController
        def delete
                Item.delete(params[:id])
        end
end
&lt;/pre&gt;
&lt;p&gt;Pour se protéger des URL forgées, on pourrait la transformer en :&lt;/p&gt;
&lt;pre&gt;
class ItemsController &amp;lt; ApplicationController
        def delete
                @item = @current_user.items.find(params[:id])
                @item.delete if @item
        end
end
&lt;/pre&gt;
&lt;p&gt;Ce n'est pas parfait (on pourrait vérifier que c'est bien une requête de
type POST), mais c'est déjà beaucoup mieux.&lt;/p&gt;
&lt;p&gt;Un dernier petit truc pour la route avant de passer à autre chose. Si vous
avez une API pour laquelle vous utilisez la sérialisation XML, il peut être
intéressant de surcharger &lt;code&gt;ActiveRecord#to_xml&lt;/code&gt; pour que le champ
&lt;code&gt;secret_field&lt;/code&gt; n'y apparaisse pas :&lt;/p&gt;
&lt;pre&gt;
class Item &amp;lt; ActiveRecord::Base
        def to_xml(args={})
                super({:except =&amp;gt; [:secret_field]}.merge(args))
        end
end
&lt;/pre&gt;
&lt;h4&gt;Cross-Site Scripting&lt;/h4&gt;
&lt;p&gt;Jusque maintenant, nous avons vu des attaques directes : un utilisateur
essaye de s'en prendre à notre site. Il existe également des attaques plus
pernicieuses que l'on classe sous le nom de &lt;a href=&quot;http://fr.wikipedia.org/wiki/Cross_site_scripting&quot;&gt;Cross-Site Scripting&lt;/a&gt;
(XSS en abrégé). Leur but est de s'en prendre aux utilisateurs de notre site en
glissant des cochonneries sur notre site. Ceci peut aller du spammeur qui
mettra une balise &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; vers son site dans tous les
formulaires qui lui passent sous la main à l'injection de javascript non
maîtrisé.&lt;/p&gt;
&lt;p&gt;Par exemple, quelqu'un crée un item dont la description est la
suivante :&lt;/p&gt;
&lt;pre&gt;
&amp;lt;script&amp;gt;document.location='http://www.programmez.com/';&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Si maintenant un visiteur affiche la description de cet item, il sera
redirigé vers le site www.programmez.com. Vous vous dites que c'est ennuyeux
mais pas bien méchant ? Oui, mais la même technique permet de voler les
cookies et donc les sessions associées. Nous allons donc chercher à nous
protéger de ces failles XSS.&lt;/p&gt;
&lt;p&gt;Pour cela, il est important de faire une distinction entre 2 cas :
est-ce que le champ que vous allez afficher peut contenir des balises HTML ou
non ? Pour afficher le nom d'un item, on sera dans le premier cas, à
savoir pas de balises HTML : on veut juste afficher le nom tel que l'a
rentré son propriétaire. Par contre, on peut souhaiter être plus souple pour la
description de l'item et laisser la possibilité d'avoir un titre (balise
&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;), du gras (&lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt;) ou de l'italique
(&lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt;). Ces 2 cas ne se traitent pas de la même façon. Pour
le premier cas, Rails nous offre un moyen simple de nous en protéger : le
helper &lt;strong&gt;&lt;code&gt;h&lt;/code&gt;&lt;/strong&gt;. En pratique, à chaque fois que l'on
souhaitera afficher le titre d'un item, on procédera de la manière
suivante :&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%=h @item.title %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Ce &lt;code&gt;h&lt;/code&gt; va convertir les caractères qui pourraient être
interprétés par un navigateur web en l'entité HTML correspondante. Problème
résolu.&lt;/p&gt;
&lt;p&gt;Le deuxième cas est par contre plus difficile à traiter. Vous pouvez être
tenté d'utiliser un moteur de formatage de texte comme &lt;a href=&quot;http://whytheluckystiff.net/ruby/redcloth/&quot;&gt;RedCloth&lt;/a&gt;. Attention, cela ne
suffit pas à filtrer &lt;a href=&quot;http://www.rorsecurity.info/2007/08/20/redcloth-security-thoughts/&quot;&gt;toutes les
attaques&lt;/a&gt; ! Pour votre tranquillité, il vaut mieux utiliser le plugin
&lt;a href=&quot;http://svn.techno-weenie.net/projects/plugins/white_list/&quot;&gt;WhiteList&lt;/a&gt;.
Depuis Rails 2.0, ce plugin fait partie du framework et peut s'utiliser de la
façon suivante :&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= sanitize @item.description, :tags =&amp;gt; %w(b i h1) %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Il est possible de déclarer les balises autorisées de manière globale :
je vous renvoie à la &lt;a href=&quot;http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html#M000936&quot;&gt;
documentation officielle&lt;/a&gt;. Et pour ceux qui veulent être sûrs de ne pas
oublier d'appel à &lt;code&gt;h&lt;/code&gt; ou à &lt;code&gt;sanitize&lt;/code&gt;, il existe des
moteurs de template alternatifs comme &lt;a href=&quot;http://wiki.rubyonrails.com/rails/pages/Safe+ERB&quot;&gt;Safe ERB&lt;/a&gt; ou &lt;a href=&quot;http://www.kuwata-lab.com/erubis/&quot;&gt;Erubis&lt;/a&gt;. Ces moteurs adoptent l'approche
opposée : ils filtrent par défaut tous les éléments &lt;code&gt;&amp;lt;%=
%&amp;gt;&lt;/code&gt;, charge au développeur d'indiquer explicitement ceux pour lequel
le moteur ne fera pas de filtrage.&lt;/p&gt;
&lt;h4&gt;Cross-Site Request Forgeries&lt;/h4&gt;
&lt;p&gt;Juste avant de finir, je voudrais juste dire un mot sur un dernier type
d'attaques. Les CSRF, abréviation de Cross-Site Request Forgery, sont des
attaques complexes qui visent à forcer l'utilisateur à envoyer une requête HTTP
vers notre site lorsque celui-ci visitera le site de l'attaquant. Je vous
renvoie à &lt;a href=&quot;http://fr.wikipedia.org/wiki/Cross-Site_Request_Forgeries&quot;&gt;wikipedia&lt;/a&gt; si
vous voulez comprendre comment fonctionne ce type d'attaques. Sachez que Rails
vous protège de celles-ci depuis la version 2.0 et qu'il existe un plugin pour
les versions plus anciennes : &lt;a href=&quot;http://svn.techno-weenie.net/projects/plugins/csrf_killer/&quot;&gt;CSRF-killer&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Nous avons pu voir qu'en prenant quelques bonnes habitudes, on pouvait
développer des applications sûres en Rails. Il reste cependant des sujets que
je n'ai pas abordés comme &lt;a href=&quot;http://www.igvita.com/blog/2006/10/10/securing-your-rails-environment/&quot;&gt;l'administration
de Rails&lt;/a&gt;, &lt;a href=&quot;http://www.rorsecurity.info/2007/03/15/apache-2-file-privileges-and-modules/&quot;&gt;apache&lt;/a&gt;
ou &lt;a href=&quot;http://www.rorsecurity.info/2007/02/25/securing-mysql/&quot;&gt;MySQL&lt;/a&gt;
(&lt;a href=&quot;http://www.rorsecurity.info/2007/02/27/rails%e2%80%99-friends-securing-mysql-continued/&quot;&gt;suite&lt;/a&gt;),
&lt;a href=&quot;http://www.rorsecurity.info/2007/03/27/working-with-files-in-rails/&quot;&gt;la
manipulation des fichiers&lt;/a&gt; ou encore &lt;a href=&quot;http://railscasts.com/episodes/9&quot;&gt;le filtrage des informations sensibles dans
les logs&lt;/a&gt;. Il est également important de se tenir au courant des mises à
jour de sécurité de Rails et des plugins que vous utilisez.&lt;/p&gt;
&lt;p&gt;Je remercie Benoît Sibaud pour sa relecture attentive.&lt;/p&gt;
&lt;h4&gt;Références&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rorsecurity.info/ruby-on-rails-security-cheatsheet/&quot; title=&quot;http://www.rorsecurity.info/ruby-on-rails-security-cheatsheet/&quot;&gt;http://www.rorsecurity.info/ruby-on...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.quarkruby.com/2007/9/20/ruby-on-rails-security-guide&quot; title=&quot;http://www.quarkruby.com/2007/9/20/ruby-on-rails-security-guide&quot;&gt;http://www.quarkruby.com/2007/9/20/...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.innerewut.de/2008/1/3/24c3-ruby-on-rails-security&quot; title=&quot;http://blog.innerewut.de/2008/1/3/24c3-ruby-on-rails-security&quot;&gt;http://blog.innerewut.de/2008/1/3/2...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.owasp.org/index.php/OWASP_AppSec_FAQ&quot; title=&quot;http://www.owasp.org/index.php/OWASP_AppSec_FAQ&quot;&gt;http://www.owasp.org/index.php/OWAS...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.owasp.org/index.php/Top_10_2007&quot; title=&quot;http://www.owasp.org/index.php/Top_10_2007&quot;&gt;http://www.owasp.org/index.php/Top_...&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://blog.menfin.info/post/2008/07/18/Rails-et-la-securite#comment-form</comments>
      <wfw:comment>http://blog.menfin.info/post/2008/07/18/Rails-et-la-securite#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.menfin.info/feed/rss2/comments/261666</wfw:commentRss>
      </item>
    
  <item>
    <title>Annonces RailsConf 2008</title>
    <link>http://blog.menfin.info/post/2008/05/08/Annonces-RailsConf-2008</link>
    <guid isPermaLink="false">urn:md5:4a0073f36d2fdbcfd3b1c144164979a3</guid>
    <pubDate>Thu, 08 May 2008 17:37:00 +0200</pubDate>
    <dc:creator>M'enfin ?!?</dc:creator>
        <category>Rails</category>
            
    <description>    &lt;p&gt;La &lt;a href=&quot;http://en.oreilly.com/rails2008/&quot;&gt;RailsConf 2008&lt;/a&gt;, la grande
messe annuelle des railers, aura lieu du 29 mai au 6 juin. A cette occasion, un
certain nombre d'annonces devrait être faites. Bien entendu, la plus attendue
sera celle de &lt;a href=&quot;http://rubyonrails.com&quot;&gt;Ruby on Rails&lt;/a&gt; 2.1. Mais
c'est loin d'être la seule. Coté framework, on devrait également entendre
parler de &lt;a href=&quot;http://www.merbivore.com/&quot;&gt;Merb&lt;/a&gt; dont la version 1.0
devrait être annoncée par ce RailsConf si tout va bien.&lt;/p&gt;
&lt;p&gt;On attend également beaucoup de choses pour les interpréteurs Ruby :
arrivée du tout nouveau &lt;a href=&quot;http://ruby.gemstone.com/&quot;&gt;MagLev&lt;/a&gt;,
&lt;a href=&quot;http://rubini.us/&quot;&gt;Rubinius&lt;/a&gt; faisant tourner des applis Rails,
&lt;a href=&quot;http://jruby.codehaus.org/&quot;&gt;JRuby&lt;/a&gt; plus rapide que l'interpréteur
Ruby officiel pour les applis Rails ? Pour le moment, ce ne sont que des
objectifs (ou au mieux des rumeurs), mais on sent une certaine agitation de ce
coté-là.&lt;/p&gt;
&lt;p&gt;Enfin, la mode est au moteur de réseaux sociaux, et le RailsConf sera
l'endroit pour en parler, mais ceci fera l'objet d'un autre post sur ce blog
;-) Bref, plein de bonnes choses en vue qui me feront regretter de ne pas
pouvoir y aller...&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.menfin.info/post/2008/05/08/Annonces-RailsConf-2008#comment-form</comments>
      <wfw:comment>http://blog.menfin.info/post/2008/05/08/Annonces-RailsConf-2008#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.menfin.info/feed/rss2/comments/237155</wfw:commentRss>
      </item>
    
</channel>
</rss>