mysql(i)_real_ escape_string,安全可靠吗?

时间:2013-03-13 15:52:54

标签: php mysql mysqli sql-injection

function Query()
{
    $args = func_get_args ();

    if (sizeof ($args) > 0)
    {
         $query = $args[0];

         for ($i = 1; $i < sizeof ($args); $i++)
                $query = preg_replace ("/\?/", "'" . mysql_real_escape_string ($args[$i]) . "'", $query, 1);
    }
    else
    {
          return FALSE;
    }

我有这样的功能。基本上,我这样做一个查询:

$this->Query('SELECT * FROM USERS WHERE Username = ? AND Points < ?', $username, $points);

它目前支持已弃用的mysql函数,但适应mysqli就像在我的班级中用mysql替换mysqli一样简单。

这是一种依赖SQL注入攻击的安全方法吗?每个问号都由mysql_real_escape_string自动清理,之前我从未遇到过问题,但是我应该使用mysqli_real_escape_string进行清理吗?

我知道有关mysqli的预处理语句,但对每个变量使用bindParam似乎对我来说有点过分了。

您怎么看?

3 个答案:

答案 0 :(得分:2)

使用绑定参数过度杀伤,应该是必需的。它将更有效地逃脱并准备您的参数。

$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent);

$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;

/* execute prepared statement */
mysqli_stmt_execute($stmt);

真的看起来有点矫枉过正吗?

Documentation

答案 1 :(得分:1)

今天非常棒的一天 - 第二次尝试连续创建合理的数据库抽象层。

  

我应该使用mysqli_real_escape_string进行清理吗?

<强>不。
仅仅因为这个功能没有消毒任何东西。

要格式化 SQL字符串文字这个函数是必须的,无法避免或替换。
因此,您正是以正确的方式使用此功能,格式化字符串并格式化无条件
那么,只要您可以使用?,您就可以查询完全安全。标记以替换实际数据(并且 - 甚至使得nitpick抱怨空闲 - 只要您使用mysql(i)_set_charset()函数设置SQL编码)。

如果有人将您的方法称为已损坏 - 只需向他们询问完整代码段的证明代码即可显示某个漏洞。

但是,让我提请你注意几件重要的事情。

  1. 动态SQL查询部分仅限于字符串。例如,这两个查询不适用于您的函数:

    SELECT * FROM table LIMIT ?,?
    SELECT * FROM table ORDER BY ?
    

    仅因为数字和标识符需要不同的格式 因此,最好使用类型提示的占位符来告诉您的函数,应用哪种格式

  2. 运行查询只是工作的一部分。你也需要得到结果。为什么不在不用不必要的电话膨胀代码的情况下获取它们呢?
  3. 应该有一种方法来插入文字?标记为查询而不解析它们。
  4. 请看一下my class,它基于与你相同的原则,但我上面提到了改进。我希望你会发现它有用或者至少值得借用一两个想法。

答案 2 :(得分:0)

如果您现在使用mysqli而不是mysql。最好使用mysqli_real_escape_string。 请注意params命令已被修改。 (%和_仍未转义)