作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
SQL注入攻击是黑客对数据库进行攻击的常用手段之一。随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。黑客通过把SQL命令插入到Web表单提交的查询字符串,最终达到欺骗服务器并执行恶意的SQL命令。
/**
* Implements hook_menu().
*/
function sql_injection_menu() {
$items = array();
$items['sql/injection'] = array(
'title' => 'SQL注入实例',
'description' => 'SQL注入实例.',
'page callback' => 'sql_injection_page_callback',
'access callback' => TRUE,
);
return $items;
}
/**
* 页面回调函数.
*/
$result = db_query("SELECT n.nid, n.title FROM
function sql_injection_page_callback(){
//假定这个type是用户通过表单输入的,为了方便,这里直接赋值了。
$type = 'page';
//$output ="123";
{node} n WHERE n.type = '$type'");
$items = array();
foreach($result as $record){
$items[] = l($record->title, "node/{$record->nid}");
}
return theme('item_list', array('items' => $items));
}
访问http://localhost/thinkindrupal/sql/injection,一切正常。我们得到想要的基本页面列表,如图所示。
图 简单的page页面标题列表
尽管这段程序也能正常工作,但是却存在安全隐患。将变量$type直接放到SQL中,这样用户就有可能发动SQL注入攻击。让我们将$type设置为:
$type = "page' UNION SELECT s.sid, s.sid FROM {sessions} s WHERE s.uid = 1 #";
假定这就是用户的输入,此时我们将得到:
图 在db_query()中不使用占位符引起的SQL注入
看到什么了?像密码一样的信息,是的,我们把用户1的会话信息也显示了出来。出问题了把。当然,这危害还比较小,黑客有可能会使用SQL注入,获取更多的信息。比如注册用户的各种个人信息。
我们来对这段代码进行改进,其实使用Drupal7中的占位符,就可以避免SQL注入。代码如下:
$result = db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = :type",array(':type' => $type));
如果用户输入的是:
$type = "page' UNION SELECT s.sid, s.sid FROM {sessions} s WHERE s.uid = 1 #";
此时结果为空。我们已经有效的防止了SQL注入攻击。
我们也可以采用动态查询的形式,代码如下所示:
$result = db_select('node', 'n')
->fields('n',array('nid','title'))
->condition('n.type',$type)
->execute();
这也同样可以避免SQL注入攻击。