Eval() et evil, c'est presque pareil

mieux protéger une application internet

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com
Certaines données ont besoin d'être chargées en AJAX. Pour échanger les données on peut se tourner vers JSON. Et si l'on veut être performant, on utilisera la méthode eval() (conversion de la réponse plus rapide). Cependant, cette fonction peut s'avérer dangereuse dans certaines situations. Elle est une nouvelle preuve qu'il faut être très vigilant avec les données provenant des tiers.

Performance contre sécurité
Eval(), très souvent mélangé par les développeurs avec le mot anglais evil, est une fonction qui permet d'exécuter une expression. Par exemple document.write(eval("2+2+2")); va afficher "6" et non pas "2+2+2" sur une page HTML.

Pourquoi est-elle utilisée pour gérer les réponses retournées en JSON ? La raison principale de cet usage est sa rapidité d'exécution par rapport à la conversion d'une chaîne de caractères en objet. Néanmoins, vous verrez plus bas qu'il vaut mieux attendre quelques millisecondes supplémentaires plutôt que de faire fuir les internautes en affichant un contenu inapproprié.

Imaginons la situation où notre application permet de saisir les données textuelles, par exemple en écrivant le commentaire sur un produit. Le client nous a imposés la pagination dynamique, sans chargement de la page. On ne va pas se soucier d'expliquer la méthode d'insertion des données. On se chargera uniquement de la partie récupération côté client (navigateur).

L'application web qu'on va décrire contient une variable JavaScript connected qui signifie si l'internaute est connecté ou pas pour gérer quelques actions d'interface supplémentaires.

Notre code HTML se présente de la manière suivante :
  
var connected = false;
$(document).ready(function() {
  $('.check').click(function() {
     var response = $.ajax({
       type: "GET",
       url: 'comment_next.php',
       async: false
     }).responseText;
     alert(connected);
     var vv = eval(response) ;
     alert(connected);
     $('#comment').html(vv);
     if(connected) {
       // do something
     }
     return false;
   });
});



<a href="#" class="check">get next comment</a>


L'utilisation eval() peut faire mal
L'internaute bien décidé de voir le commentaire suivant clique sur "get next comment". A ce moment-là notre application web appelle la page comment_next.php qui contient le code suivant (imaginons que c'est un commentaire):


connected = true;


La méthode $.ajax charge ce contenu, le passe ensuite à eval() qui s'occupe de l'exécution. Grâce à des alert() rajoutés avant et après le traitement on s'aperçoit que la valeur de la variable connected a changé de false en true.

Qu'est-ce que l'attaquant peut faire avec un tel cadeau ? Il peut, par exemple, afficher le contenu accessible uniquement pour les utilisateurs connectés. Dans les pires des cas il peut supprimer des éléments directement de la base.

Science Fiction
Bien sûr, le cas décrit ci-dessus est très extrême. Tout d'abord peu de développeurs web utiliseront la méthode eval() pour traiter des données susceptibles d'être modifiées par les tiers personnes. Deuxièmement, encore moins de personnes vont développer une application web basée 100% en JavaScript et actions côté client. L'objectif principal de l'article consiste en sensibilisation des lecteurs à l'emploi de la méthode eval().

L’article écrit en rythme de:
Perle Lama - C'est toi
Bartosz KONIECZNY 16-04-2011 17:53 sécurité des applications web
Un conseil MySQL

Vous rencontrez un problème lors de la suppression d'un élément ou d'une table liée à des contraintes des clés étrangères. L'une des solution peut être l'annulation de la vérification de ces contraintes.


-- Au début on indique à MySQL de ne pas vérifier les contraintes des clés étrangères
SET FOREIGN_KEY_CHECKS=0;
-- Ensuite on passe à l'opération de suppression d'une table
DROP TABLE ma_table;
-- A la fin (ou au moment voulu) on restaure la vérification des contraintes
SET FOREIGN_KEY_CHECKS=1;

Vous pouvez en savoir plus sur FOREIGN_KEY_CHEKS dans la documentation du MySQL.