原文链接:http://drupal.org/node/101496
Drupal提供了几个函数发送数据库查询。标准的形式是db_query。使用Drupal提供的函数进行数据库存取防止SQL注入。然而,仅仅使用函数是不足的见下面的例子说明:<?php
/** Example 1 - Insecure
  * SQL injection via $type
  * Display node titles of type $type (input supplied by the user via a form textfield)
  */
$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);
?>
示例1显示了一个根据用户提供的参数类型的标题列表。当$type是一个page时一个页面的结点将被检索,当$type是story时是一个story结点列表。不幸的是,这个例子是很容易受SQL攻击注入的。该漏洞可以被用在数据库与UMION支持(MySQL 4.1+)获得管理员通过提供的类型访问站点:story' UNION SELECT s.sid, s.sid FROM {sessions} s WHERE s.uid = 1/*。
这将导致执行以下查询:
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/*'
作为片段将为管理员用户账户显示有效的会话id,攻击者可以指导他或她的浏览器使用id和充分的权限在网站上。
参数化查询防止SQL注入
防止SQL注入很容易;db_query提供的一种方式参数化查询。Drupal数据库函数代替 sprintf-like占位符正确转义参数出现的顺序。<?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);
?>
API documentation中有效的占位符:
- %d - integers
- %f - floats
- %s - strings, enclose in ''
- %b - binary data, do not enclose in ''
- %% - replaced with %
<?php
/** Example 1 - Corrected
  * Display node titles of type $type (input supplied by the user via a form textfield)
  */
$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);
?>
多参数
有时候你需要注入多参数的查询,使用IN()函数。 Drupal5中你应该使用这样的代码:<?php
// Prepare $placeholders to be, e.g., "%d, %d, %d, %d, %d"
$placeholders = implode(',', array_fill(0, count($from_user), "%d"));
db_query("SELECT t.s FROM {table} t WHERE t.field IN ($placeholders)", $from_user); 
?>
Drupal6提供了db_placeholders。例如:
<?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); 
?>
对于Drupal7,见 Database API documentation。