“mysqli_real_escape_string”是不是足以避免 SQL 注入或其他 SQL 攻击?

Posted

技术标签:

【中文标题】“mysqli_real_escape_string”是不是足以避免 SQL 注入或其他 SQL 攻击?【英文标题】:Is "mysqli_real_escape_string" enough to avoid SQL injection or other SQL attacks?“mysqli_real_escape_string”是否足以避免 SQL 注入或其他 SQL 攻击? 【发布时间】:2015-11-30 05:08:34 【问题描述】:

这是我的代码:

  $email= mysqli_real_escape_string($db_con,$_POST['email']);
  $psw= mysqli_real_escape_string($db_con,$_POST['psw']);

  $query = "INSERT INTO `users` (`email`,`psw`) VALUES ('".$email."','".$psw."')";

谁能告诉我它是否安全,或者它是否容易受到 SQL 注入攻击或其他 SQL 攻击?

【问题讨论】:

SQL injection that gets around mysql_real_escape_string() 的可能重复项 我不知道怎么做。 mysqli_real_escape_string() 是一个与 mysql_real_escape_string() 完全不同的函数......也许大多数人在 2015 年还不知道? 【参考方案1】:

谁能告诉我它是否安全,或者它是否容易受到 SQL 注入攻击或其他 SQL 攻击?

不。正如uri2x所说,见SQL injection that gets around mysql_real_escape_string()

The best way to prevent SQL injection is to use prepared statements. 他们将数据(您的参数)与指令(SQL 查询字符串)分开,并且不会为数据留下任何空间来污染您的查询结构。准备好的语句解决了fundamental problems of application security 之一。

对于不能使用准备好的语句的情况(例如LIMIT),为每个特定目的使用非常严格的白名单是保证安全的唯一方法。

// This is a string literal whitelist
switch ($sortby) 
    case 'column_b':
    case 'col_c':
        // If it literally matches here, it's safe to use
        break;
    default:
        $sortby = 'rowid';


// Only numeric characters will pass through this part of the code thanks to type casting
$start = (int) $start;
$howmany = (int) $howmany;
if ($start < 0) 
    $start = 0;

if ($howmany < 1) 
    $howmany = 1;


// The actual query execution
$stmt = $db->prepare(
    "SELECT * FROM table WHERE col = ? ORDER BY $sortby ASC LIMIT $start, $howmany"
);
$stmt->execute(['value']);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);

我认为上述代码不受 SQL 注入的影响,即使在模糊的边缘情况下也是如此。如果您使用的是 MySQL,请确保关闭模拟准备。

$db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);

【讨论】:

说“这是最好的方法”并不能回答“这样就够了吗?”的问题 答案是“否”。我回答的第一句话是“看这个例子”,这证明这还不够。

以上是关于“mysqli_real_escape_string”是不是足以避免 SQL 注入或其他 SQL 攻击?的主要内容,如果未能解决你的问题,请参考以下文章