防止对具有变量(和大)列数的查询进行sql注入

时间:2012-11-16 03:27:35

标签: php mysql pdo sql-injection

我有一个使用php生成的SQL查询。它返回任何记录的代理键,该记录具有与搜索词匹配的字段以及在与搜索词匹配的其他表中具有相关记录的任何记录。

我将表连接成一个然后使用单独的函数来检索表中包含的列的列表(我希望允许添加表而不重写PHP代码以降低持续维护)。

然后使用此代码

foreach ($col_array as $cur_col) {
    foreach ($search_terms_array as $term_searching) {
        $qry_string.="UPPER(";
        $qry_string.=$cur_col;
        $qry_string.=") like '%";
        $qry_string.=strtoupper($term_searching);
        $qry_string.="%' or ";
    }
}

生成查询字符串的其余部分

select tbl_sub_model.sub_model_sk from tbl_sub_model inner join [about 10 other tables]

    where [much code removed] or UPPER(tbl_model.image_id) like '%HONDA%' or
 UPPER(tbl_model.image_id) like '%ACCORD%' or UPPER(tbl_badge.sub_model_sk) like '%HONDA%'
 or UPPER(tbl_badge.sub_model_sk) like '%ACCORD%' or UPPER(tbl_badge.badge) like '%HONDA%'
 or UPPER(tbl_badge.badge) like '%ACCORD%' group by tbl_sub_model.sub_model_sk

它做了我想要它做的事情,但它容易受到sql注入。我一直在用pdo替换我的mysql_ *代码以防止这种情况,但我将如何确保这个代码超出我的范围。

所以我的问题是,如何以安全的方式搜索所有这些表?

2 个答案:

答案 0 :(得分:0)

这是一个解决方案,要求数据库大写搜索条件,并用'%'通配符装饰它们:

$parameters = array();
$conditions = array();
foreach ($col_array as $cur_col) {
    foreach ($search_terms_array as $term_searching) {
        $conditions[] = "UPPER( $cur_col ) LIKE CONCAT('%', UPPER(?), '%')";
        $parameters[] = $term_searching;
    }
}

$STH = $DBH->prepare('SELECT fields FROM tbl WHERE ' . implode(' OR ', $conditions));
$STH->execute($parameters);

备注:

  1. 我们让MySQL在用户的搜索词上调用UPPER(),而不是让PHP调用strtoupper()
    这应该限制可能的搞笑/混淆不匹配的字符集问题。所有规范化都发生在一个地方,并且尽可能接近使用时刻。
  2. CONCAT()是特定于MySQL的 但是,当您标记问题[mysql]时,这可能不是问题。
  3. 此查询与原始查询一样,将无视索引。

答案 1 :(得分:-1)

尝试使用数组来保存参数。注意%在术语之前和之后添加,因为 LIKE%?%在查询字符串中不起作用PHP Manual

    //Create array to hold $term_searching
    $data = array();
    foreach ($col_array as $cur_col) {
        foreach ($search_terms_array as $term_searching) {
            $item = "%".strtoupper($term_searching)."%";//LIKE %?% does not work
            array_push($data,$item) 
            $qry_string.="UPPER(";
            $qry_string.=$cur_col;
            $qry_string.=") LIKE ? OR";
        }
}
$qry_string = substr($qry_string, 0, -3);//Added to remove last OR

$STH = $DBH->prepare("SELECT fields FROM table WHERE ". $qry_string);//prepare added 
$STH->execute($data);  

编辑

添加

$qry_string = substr($qry_string, 0, -3)以删除上次出现的 OR prepare添加到$STH = $DBH->prepare("SElECT fields FROM table WHERE". $qry_string)