Voilà, voilà... Fin de l'aventure...

 

Fermeture de kolossaldrupal.org dans...


Bonjour tout le monde,

Drupal évolue, les versions changent et Kolossaldrupal.org était essentiellement consacré à la version 6 de Drupal.

Autant dire que les infos présentées ici commencent à dater...

Faute de temps, je ne peux plus garder le site Kolossaldrupal à jour...

Je vous aurais bien proposé de reprendre le flambeau mais... c'est tellement simple de nos jours de se faire son propre site à soi...Pourquoi s'embêter alors ? :-)

Ce site restera donc en l'état, tel qu'il était en 2011...

Ah la la ! Cela ne nous rajeunit pas !

Manuel Vila - Avril 2016

Accès à la base de données

Référence sur drupal.org : 18 Mai 2009 – 20h51 - http://drupal.org/node/101496


Drupal fournit plusieurs fonctions pour envoyer des requêtes à la base de données. La forme classique est db_query. Utilisez toujours ces fonctions pour éviter les attaques par injection SQL. Cependant, n’utiliser que ces fonctions n’est pas suffisant, comme le montre l’exemple suivant :

<?php
/** Exemple 1 - Risqué
  * SQL injection via $type
 * Affiche les titres de nodes du type $type (indiqué par l'utilisateur vie une zone de saisie de formulaire)
*/
$result db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = '$type'");

$items = array();
while (
$row db_fetch_object($result)) {
  
$items[] = l($row->title"node/{$row->nid}");
}
return 
theme('item_list'$items);
?>

Cet exemple affiche une liste de titres dépendants de l’argument fourni par l’utilisateur. Une liste de nodes page sera extraite lorsque $type sera page, une liste de nodes articles lorsque $type sera article. Malheureusement, cet exemple est vulnérable à une injection SQL.

La vulnérabilité peut être utilisée sur les bases de données supportant UNION (MySQL 4.1+) en obtenant un accès utilisateur au site, en indiquant comme type : story' UNION SELECT s.sid, s.sid FROM {sessions} s WHERE s.uid = 1/*.

Ce qui générera la requête suivante :

SELECT n.nid, n.title FROM {node} n WHERE n.type = 'story' UNION SELECT s.sid, s.sid FROM {sessions} s WHERE s.uid = 1/*'

Comme ce code affichera des ID de session valides pour le compte administrateur, un agresseur pourra indiquer à son navigateur d’utiliser ces ID et aura tous les droits sur le site.

Les requêtes paramétrées empêchent les injections SQL

Empêcher l’injection SQL est facile : db_query fournit une méthode d’utilisation des requêtes paramétrées. Les fonctions de bases de données de Drupal remplacent le caractère de substitution avec l’argument correctement échappé, dans leur ordre d’apparition.

<?php
db_query
("SELECT n.nid FROM {node} n WHERE n.nid > %d"$nid);
db_query("SELECT n.nid FROM {node} n WHERE n.type = '%s'"$type);
db_query("SELECT n.nid FROM {node} n WHERE n.nid > %d AND n.type = '%s'"$nid$type);
db_query("SELECT n.nid FROM {node} n WHERE n.type = '%s' AND n.nid > %d"$type$nid);
?>

Les caractères de substitution valides sont renseignés dans la documentation de l’API :

  • %d – entiers
  • %f - flottants
  • %s – chaînes, entourées de ’’
  • %b – données binaires, non entourées de ’’
  • %% - remplacé par %

Voici le premier exemple corrigé :

<?php
/** Exemple 1 - Corrigé
  * Affiche les titres de nodes du type $type (indiqué par l'utilisateur vie une zone de saisie de formulaire)
  */
$result db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = '%s'"$type);

$items = array();
while (
$row db_fetch_object($result)) {
  
$items[] = l($row->title"node/{$row->nid}");
}
return 
theme('item_list'$items);
?>

Arguments multiples

De temps à autre, vous aurez besoin d’injecter plusieurs arguments dans une requête, en utilisant la fonction IN().

Dans Drupal 5, vous utiliserez ce code :

<?php
$placeholders 
implode(','array_fill(0count($from_user), "%d"));

db_query("SELECT t.s FROM {table} t WHERE t.field IN ($placeholders)"$from_user); 
?>

A partir de Drupal 6, une fonction db_placeholders est disponible. Exemple :

<?php
$values 
= array(12345);

$placeholders db_placeholders($values);

db_query("SELECT t.s FROM {table} t WHERE t.field IN ($placeholders)"$values); 
?>