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

标签 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 注入(inject)的攻击。我一直在用 pdo 替换我的 mysql_* 代码以防止这种情况发生,但是我将如何保护这个代码超出了我的范围。

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

最佳答案

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

$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. 此查询与您的原始查询一样,将无法建立索引。

关于php - 防止对具有可变(和大)列数的查询进行 sql 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13409929/

相关文章:

php - 将可变数量的参数传递到 PDO 语句并返回 JSON 对象

php - PDO 获取结果或 while 循环中的 bool 值

PHP yield 与 PDO 获取?

php - 如何更正 MySQL 表 ID?

php - 在 Observer 方法中,如何告诉 Magento 在分派(dispatch)事件后不处理代码

mysql - 选择一列中具有相同值的行,但不要选择那些单独的行

mysql - 警告 : #1265 Data truncated for column 'pdd' at row 1

php - 插入大约30次MYSQL

php - 如何获取已登录站点的用户的 session ID

javascript - 如何限制mysql数据库输入的行数