为什么Mysqli准备语句不会逃脱通配符(%和_)和反斜杠(\)?

时间:2014-02-28 07:27:09

标签: php mysql mysqli prepared-statement sql-injection

作为安全措施,我使用的是Mysqli预处理语句和bindvariables。

我的代码如下所示:

$what = trim($_GET['what']);
$key_word = "%".$what."%";  
$where_clause = " WHERE chair.company LIKE ? OR chair.business_category LIKE ? OR chair.summary LIKE ?";
$query = "SELECT chair.id_user, chair.company   FROM chair" . $where_clause; 
$con = @mysqli_connect($hostname,$username,$password, $database_name);
$stmt = mysqli_prepare($con, $query);
$bind = mysqli_stmt_bind_param($stmt, 'sss', $key_word, $key_word, $key_word);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$bind = mysqli_stmt_bind_result($stmt,$business_id,$company);
while (mysqli_stmt_fetch($stmt))
    {
    echo htmlspecialchars($company)."<br>";
    }

来自Documentation

  

作为显式转义特殊字符的替代方法,许多MySQL API提供占位符功能,使您能够将特殊标记插入到语句字符串中,然后在发出语句时将数据值绑定到它们。在这种情况下,API负责为您转义值中的特殊字符。

我可以使用键盘中的所有字符(不包括\%_)并正确转义和匹配。 我的问题是这个准备好的语句不会转义外卡(%和_)和转义字符(\)。当我搜索%时,它会列出数据库中的所有项目。当我搜索_它列出所有项目。 当搜索(\)时,它与所需的项目不匹配。

我找到了similar Question,但是amswer永远不符合我的要求,因为我必须在我的查询中使用通配符。

Another Question回答说要逃避它们使用双反斜杠

即使这不是一个安全问题,为什么准备好的声明并没有逃脱它们? 我在代码中使用它的方式有什么错误吗? 如何动态逃脱它们?我可以使用哪种功能?

1 个答案:

答案 0 :(得分:1)

准备好的语句执行正确地逃避\。否则,他们将无法创建格式正确的string literals,这是预准备语句的主要目的。

除此之外,%_只是LIKE comparison的特殊字符,而不是一般的字符串。所以一般来说没有必要逃避它们。如果您需要通过LIKE比较来转义它们,请明确地执行:

$what = addcslashes($what, '%_');

除此之外,LIKE还支持使用\以外的转义字符:

mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
        -> 1