Sécurité

Cookies

Et voilà sur le même thème un petit billet en français pour les non anglophones.

Nous avons libéré sur github une petite classe qui installe un gestionnaire de session personnalisé. Sa particularité est de stocker les données de session dans un cookie chiffré.

L'intérêt est que nous n'avons plus besoin de partager les sessions entre serveurs si nous avons plusieurs frontaux.

Le chiffrement permet d'éviter toute modification par l'utilisateur du contenu du cookie. Le chiffrement par défaut utilise la paquet pear Crypt_Blowfish.

Son utilisation est très simple, on utilise toujours les fonctions habituelles de gestion de session (session_start(), session_destroy(), etc.). La seule exigence est de fermer la session en écriture juste avant la sortie HTML/whatever.

<?php
// just include session class
require_once 'session.php';
require_once 
'Crypt/Blowfish.php'// pear package, only needed when using SessionInCookie_DefaultCipher

SessionInCookie::setCipher(new SessionInCookie_DefaultCipher('mysecretkey'));

// start session normally
start_session();

// Read and write in session
$_SESSION['foo'] = 'bar';

// juste before output, call session_write_close
session_write_close();

// WARNING: now session data have been send to the client via encrypted cookie. You *CANNOT* write on $_SESSION.

echo 'Hello Word';
?>

Vous pouvez retrouver le code sur le dépot session-cookie. L'utilisation est décrite dans le README.

Madison Street cable car derailed in snow, 1929

Quand on développe une application web, la sécurité est toujours une problématique à prendre au sérieux. Négligez-la et vous pouvez être sûr qu'un jour ou l'autre, un petit malin se fera le plaisir de vous montrer vos failles. Une attaque simple mais très répandue est l'injection XSS (ou Cross-site scripting). Le principe est d'envoyer du code HTML dans un site web pour qu'il soit interprété par le navigateur d'un autre utilisateur. Par exemple, on peut poster la ligne suivante sur un forum pour essayer d'ennuyer les autres utilisateurs :

  1. <script>alert('All your base are belong to us!');</script>

Cette attaque n'est toutefois pas à prendre à la légère. Elle permet par exemple de voler les cookies d'un utilisateur et donc sa session, ou encore de lui faire des actions indésirables sur le site attaqué.

Il est donc nécessaire de se protéger de cette attaque et, rassurez-vous, Ruby on Rails a tout ce qu'il faut pour faire ça simplement. Jusqu'à maintenant, la méthode pour faire ça consiste à indiquer à Rails les chaînes de caractères qui contiennent du contenu manipulé par l'utilisateur et qui pourraient donc être dangereuses. Dans le cas le plus fréquent, une telle chaîne ne doit pas du tout contenir de balise HTML, et on peut alors utiliser le helper h qui transforme les caractères dangereux en entités HTML. Exemple :

  1. Hello <%=h @name %>

Dans le cas contraire où l'utilisateur a le droit d'entrer du texte HTMl enrichi avec des balises HTML, il convient de limiter les balises et attributs autorisés. Le helper sanitize permet de faire ça :

  1. Biographie : <%=sanitize @bio %>

Cela fonctionne très bien, mais il y a toujours le risque d'oublier un h ou un sanitize, ce qui laisserait une porte pour un attaquant. C'est pourquoi il existe des plugins Rails qui favorisent l'approche inverse, à savoir indiquer quelles sont les chaînes de caractères qui sont sûres et d'échapper tout le reste. C'est également l'approche que Rails 3 offrira lors de sa sortie en février 2010.

Dans Rails 3, les chaînes de caractères auront un attribut html_safe, qui indiquera si la chaîne est sûre. Par défaut, l'attribut vaudra false, et cette chaîne sera échappée lors du rendering.

Bien entendu, votre page HTML contient des balises et il est donc nécessaire de pouvoir construire ces balises sans qu'elles soient échappées. Tout d'abord, cette protection ne vise que des contenus venant de l'utilisateur, il est donc inutile d'échapper le contenu "en dur" des vues : seul ce qui se trouvent entre <%= et %> est concerné. Dans l'exemple suivant, le nom apparaîtra bien en gras :

  1. Hello <strong><%= @name %></strong>

Une autre source de contenus légitimes est la génération de code HTML par les helpers de Rails. Heureusement, ces helpers génèrent des chaînes de caractères marquées comme sûres après avoir échappé leurs entrées. Exemple :

  1. <%= tag(:p, "<script>alert('hello');</script>") %>  # => "<p>&lt;script&gt;alert('hello');&lt;script&gt;</p>"

Enfin, il vous reste la possibilité de marquer vous-mêmes les chaînes comme étant sûres. Pour cela, vous pouvez utilisez raw quand vous êtes dans une vue, ou appeler html_safe sur la chaîne si vous êtes dans un helper. Exemple :

  1. <%= raw @site_title %>
  1. def evil_js
  2.   "<script>alert('This site is evil. Mwahahah!');</script>".html_safe
  3. end

Si vous souhaitez en savoir plus, je vous conseille la lecture de SafeBuffers and Rails 3.0 de Yehuda Katz.

Logo
Chaque semaine, je publie une liste de liens vers des billets de blog, des articles et des annonces qui me semblent intéressants et en rapport avec l’activité d’AF83. N’hésitez pas à proposez vos liens. Voici la sélection de cette semaine :
Campagne Microsoft