在php中输入卫生设施

时间:2011-08-21 10:50:52

标签: php mysql sql-injection

我知道sql注入已经在stackoverflow上讨论了很多次。

使用此方法有什么缺点

foreach($_POST as &$value)
    $value = mysql_real_escape_string($value);

它只有两行,看起来使用起来非常方便,但我认为这不是一个非常常用的方法。

请不要将讨论转变为准备好的陈述和PDO,即使它可能被认为是最佳实践。

7 个答案:

答案 0 :(得分:6)

使用此代码的主要缺点是您正在修改POST数组中的数据。这可能会影响稍后对POST数组的操作(如输出到屏幕)。如果您正在与其他程序员合作,他们可以合理地期望POST阵列保持不变,这也可能导致混淆。由于上一个原因,它还可能使代码维护更加困难。任何处理代码的人都需要知道你修改了POST数组。

我的建议是,如果你开始使用mysql_real_escape_string而不是参数化查询,那就是确保你将它与sprintf和正确的类型说明符结合使用,如下所示:

$query = sprintf("INSERT INTO purchases (amount, num_items, prod_descrip) 
                    VALUES (%f, %d, '%s')",
                    mysql_real_escape_string($_POST['amount'])
                    mysql_real_escape_string($_POST['num_items'])
                    mysql_real_escape_string($_POST['prod_descrip']));

请注意,%f适用于float,%d适用于整数,%s适用于字符串值。另请注意,我在查询字符串中直接使用$ _POST数据而没有任何类型的验证,我在实践中不会这样做(仅为了简单起见)。

答案 1 :(得分:4)

任何数据都不应该在收集时被转义,但在使用它时,因为您可能在不同的上下文中使用相同的数据(MySQL查询,preg模式,HTML输出),并且每个上下文都需要不同的转义。此外,如果您以这种方式转义数据,那么您正在使用其他数据源做什么,假设您正在从文件或远程XML服务中读取值?很容易忘记逃避它,并且很容易忘记哪些值被转义而哪些没有,要么让您的应用程序易受攻击,要么以双重转义结束。正如@genesisφ所指出的,上述方法也应该是递归的,以处理数组。并且您需要在查询中的每个值周围使用引号,包括数字,否则您很容易受到这些参数中的SQL注入攻击。

答案 2 :(得分:3)

如果您希望为MySQL查询正确格式化每个POST变量,则此方法才有意义。

这与Magic Quotes背后的理论基本相同,后者因为有充分理由而被弃用。

答案 3 :(得分:2)

我不会用这个。有些情况下你只需要intval或你传递POST数组,这将在这里出错。您可以使用自己的函数

简化每次编写mysql_real_escape_string()的过程
function mres($what){
    return mysql_real_escape_string($what);
}

并使用它

$query = '
    select column 
    from table 
    where column2 = "'.mres($_POST['var']).'"';

答案 4 :(得分:1)

在处理POST / GET数据之前逃避POST / GET数据并不是一个好习惯。通常,在创建查询时应该转义数据。例如:

$query = '
    select column_name 
    from table_name 
    where column_name = "'. mysql_real_escape_string($_POST['var_name']) .'"
';

答案 5 :(得分:0)

为了提高效率,我建议这样的事情

$dbArr = array( 'key1','key2',...); //make these keys correspond with the POST vars you want in the db

foreach($dbArr as $goodCol){

    $sanitized[$goodCol] = mysql_real_escape_string($_POST[$goodCol]);

}

答案 6 :(得分:0)

如果您喜欢正则表达式并想要明确控制输入,请试试这个。

function match_implode($filter,$val,$cut=255){
    $m=array();
    if(!is_string($val)){
        return false;
    }
    preg_match_all($filter,$val,$m);
    if(!empty($m[0])){
        return substr(implode($m[0]),0,$cut);
    }
    return false;
}
//Only Alpha-numeric with a max-length of 20 chars.
echo match_implode("{[A-Za-z0-9]}",$_POST["alpha"],20);

//Practical use
if($user_id=match_implode("{[0-9]}",$_POST["id"])){
    mysql_query("UPDATE user SET last_login=UNIX_TIMESTAMP() WHERE user_id=$user_id");
}

//If you need to parse and escape email :)
if($email=match_implode("{^[a-z0-9\å\ä\ö._-]+@[a-z0-9\å\ä\ö.-]+\.[a-z]{2,6}$}i",$_POST["email"])){
    mysql_query("UPDATE user SET last_login=UNIX_TIMESTAMP() WHERE email='$email'");
}