Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/229.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP:使用准备好的语句并防止SQL注入与转义_Php_Prepared Statement_Sql Injection_Mysql Real Escape String - Fatal编程技术网

PHP:使用准备好的语句并防止SQL注入与转义

PHP:使用准备好的语句并防止SQL注入与转义,php,prepared-statement,sql-injection,mysql-real-escape-string,Php,Prepared Statement,Sql Injection,Mysql Real Escape String,我确实理解,准备好的语句是针对SQL注入寻求保护的最终方法。但是,它们提供的覆盖范围有限;例如,在我让用户决定如何按操作排序的情况下(即,是ASC还是DESC?等),我没有得到准备好的语句的覆盖 我知道我可以将用户输入映射到预定义的白名单。但是,这只有在事先可以创建或完全猜测白名单的情况下才可能实现 例如,在我上面提到的情况下(ASC或DESC),可以很容易地根据接受值列表映射和验证。但是,难道不存在无法对照白名单验证SQL语句部分的情况吗 如果存在这种情况,那么推荐的方法是什么 如果我要使用底

我确实理解,准备好的语句是针对SQL注入寻求保护的最终方法。但是,它们提供的覆盖范围有限;例如,在我让用户决定如何按操作排序的情况下(即,是ASC还是DESC?等),我没有得到准备好的语句的覆盖

我知道我可以将用户输入映射到预定义的白名单。但是,这只有在事先可以创建或完全猜测白名单的情况下才可能实现

例如,在我上面提到的情况下(ASC或DESC),可以很容易地根据接受值列表映射和验证。但是,难道不存在无法对照白名单验证SQL语句部分的情况吗

如果存在这种情况,那么推荐的方法是什么

如果我要使用底层数据库的内置转义实用程序(例如mysqL的mysqL\u real\u escape\u string)全面转义用户输入,我会在哪里失败

我问这个问题的前提是我总是用引号来构造sql语句——即使是整数

让我们看一看下面的例子并思考一下

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}
假设所有变量都是用户提供的

如果我使用mysql\u real\u escape\u string来处理上述SQL中的所有变量(而不是使用只覆盖了我一半的预处理语句,迫使我为另一半列出白名单,这是无法帮助的),那么它不是同样安全(并且更容易编码)?如果不是,在哪个输入场景中转义实用程序会失败

$fields       = mysql_escape($fields);
$table        = mysql_escape($table);
$age          = mysql_escape($age);
$orderby_pref = mysql_escape($orderby_pref);

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}

你可以使用PDO,你的生活会变得更轻松…:

    #   Order
    switch(strtoupper($Order)){
        default:
        case 'ASC':
            $Order = 'ASC';
            break;

        case 'DESC':
            $Order = 'DESC';
            break;
    }

    #   ID
    $ID = 39;
    $Username = 'David';

    #   Query
    $Query = $this->DB->Main->prepare('SELECT * FROM Table WHERE ID = :ID AND Username = :Username ORDER BY HellBob '.$Order);
    $Query->bindValue(':ID', $ID, PDO::PARAM_INT);
    $Query->bindValue(':Username', $Username, PDO::PARAM_STR);

    #   All good ?
    if(!$Query->execute()){
        exit('Error');
    }

    // Results
    $Row = $Query->fetch(PDO::FETCH_ASSOC);

您不必担心引号或SQL注入。您可以使用您提到的简单的“白名单”将变量放入查询。

无论您使用的是预先准备好的语句还是
mysql
转义函数,对于表名或列名等内容,您始终需要使用白名单

问题是表名和列名不能用单引号或双引号引起来,因此如果您使用一个函数专门引用这些字符(当然还有更多的字符…),那么它对表名没有任何作用

考虑表名
my_表;从mysql中删除*;从我的表格中选择*
。这个字符串中的任何内容都不会被mysql的转义函数转义,但它肯定是一个您希望对照白名单检查的字符串


除此之外,
mysql
转义函数在字符集方面存在问题,这些字符集可能会使它们变得无用,因此您最好使用预先准备好的语句。

您忘记了排序字段;-)这并不能真正回答问题,因为您已经在查询中硬编码了表名、列名和排序顺序列。然后,您可以使用白名单来编写表名。除了白名单之外,没有其他安全的方法。向上投票是因为您知道并关心sql注入(与大多数人在PHP标签中提问相反),动态sql和向查询中添加值之间存在差异。绑定参数或字符串连接(加上转义)都可以用于添加值。动态SQL需要白名单可接受的语法。因此,可以使用regex、map或switch语句来添加
DESC
ORDER
和其他限定符。不过,存储过程将是一个冗长的选择;从mysql中删除*;从my_表中选择*可以很好地确定MYSQL_转义方法失败的原因。。。。因此,简单地说,SQL注入保护的唯一替代方案(对于准备好的语句或db的转义实用程序没有帮助的部分)是使用白名单方法。这个结论正确吗?