不做任何修改直接將使用者輸入插入 SQL 查詢會使應用程式容易受到 SQL 注入攻擊。為了防止這種情況發生,將資料與 SQL 分離以確保資料保留為資料並且永遠不會被 SQL 解析器解釋為命令。
最有效的解決方案
避免SQL 注入攻擊的推薦方法,無論使用什麼資料庫,都是使用準備好的語句和參數化查詢。這些是由資料庫伺服器獨立解析的 SQL 語句以及參數。這種方法使攻擊者無法注入惡意 SQL。
使用 PDO 或 MySQLi 實作
PDO 為所有受支援的資料庫驅動程式提供通用解決方案,而 MySQLi 則是特定的到 MySQLi。
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name'); $stmt->execute(['name' => $name]); foreach ($stmt as $row) { // Do something with $row }
$result = $db->execute_query('SELECT * FROM employees WHERE name = ?', [$name]); while ($row = $result->fetch_assoc()) { // Do something with $row }
$stmt = $db->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); // 's' specifies string type $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // Do something with $row }
正確的連接設定
當使用PDO for MySQL 時,請透過停用來確保使用真正的準備好的語句
$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8mb4', 'user', 'password'); $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
對於MySQLi,使用以下內容:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // error reporting $dbConnection = new mysqli('127.0.0.1', 'username', 'password', 'test'); $dbConnection->set_charset('utf8mb4'); // charset
說明
準備好的語句由資料庫伺服器解析和編譯,將 SQL 語句與參數分開。參數傳遞時,會以字串形式與編譯後的語句組合在一起,消除 SQL 注入的風險。
動態查詢
Prepared statements 可用於動態查詢中的參數,動態查詢結構本身不能參數化。在這些情況下,建議使用白名單過濾器。
以上是如何有效防止PHP應用中的SQL注入?的詳細內容。更多資訊請關注PHP中文網其他相關文章!