在 PHP 中防止 SQL 注入攻击

Prevent SQL injection attack in PHP

我想防止SQL对这段PHP代码的攻击(这只是class中的练习)。这可以很容易地通过设置 @mail 等于 '); DROP TABLE PURCHASE; --

来利用
$db = new SQLite3 ($db_name);

$sql = sprintf ("INSERT INTO PURCHASE (quantity, name, password, mail) 
                 VALUES ('%s', '%s', '%s', '%s')\n",
                 $Quantity, $Name, $Password, $Mail );

echo $sql;
if (!$db->exec ($sql)) {
    throw new Exception($db->lastErrorMsg());
}

我试图通过传递这样的参数来防止这种情况,但我得到 500 Internal Server Error

$db = new SQLite3 ($db_name);

$sql = $db->prepare("INSERT INTO PURCHASE(quantity, name, password, mail)
            VALUES (:Quantity, :Name, :Password, :Mail)");

$sql->bindValue(':Quantity', $Quantity, SQLITE3_TEXT);
$sql->bindValue(':Name', $Name, SQLITE3_TEXT);
$sql->bindValue(':Password', $Password, SQLITE3_TEXT);
$sql->bindValue(':Mail', $Mail, SQLITE3_TEXT);

echo $sql;
if (!$db->exec ($sql)) {
    throw new Exception($db->lastErrorMsg());
}

我该如何解决这个问题?

SQLite3::exec is for executing a query string, not a prepared statement. You need to use SQLite3Stmt::execute 代替。变化:

if (!$db->exec ($sql)) {
    throw new Exception($db->lastErrorMsg());
}

if (!$sql->execute()) {
    throw new Exception($db->lastErrorMsg());
}

请注意,您不能 echo $sql,因为它是一个对象,而不是简单类型。如果您想查看 SQLite3Stmt 对象的外观,则需要 print_r($sql)var_dump($sql).