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 :
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(0, count($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(1, 2, 3, 4, 5);
$placeholders = db_placeholders($values);
db_query("SELECT t.s FROM {table} t WHERE t.field IN ($placeholders)", $values);
?>- Version imprimable
- 5160 lectures
-

Commentaires
Poster un nouveau commentaire