原文链接: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。