国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

PHP中如何防止SQL注入?
P粉128563140
P粉128563140 2023-08-31 18:10:38
0
2
765
<p>如果用戶輸入未經(jīng)修改就插入到 SQL 查詢中,則應用程序很容易受到 SQL 注入的攻擊,如下例所示:</p> <pre class="lang-php prettyprint-override"><code>$unsafe_variable = $_POST['user_input']; mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')"); </code></pre> <p>這是因為用戶可以輸入類似 <code>value') 的內(nèi)容; DROP TABLE table;--</code>,查詢變?yōu)椋?lt;/p> <pre class="brush:php;toolbar:false;">INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')</pre> <p>可以采取什么措施來防止這種情況發(fā)生?</p>
P粉128563140
P粉128563140

全部回復(2)
P粉238355860

要使用參數(shù)化查詢,您需要使用 Mysqli 或 PDO。要使用 mysqli 重寫您的示例,我們需要如下內(nèi)容。

<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("server", "username", "password", "database_name");

$variable = $_POST["user-input"];
$stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)");
// "s" means the database expects a string
$stmt->bind_param("s", $variable);
$stmt->execute();

您需要閱讀的關鍵函數(shù)是 mysqli::prepare.

此外,正如其他人所建議的,您可能會發(fā)現(xiàn)使用諸如 PDO.

請注意,您詢問的案例相當簡單,更復雜的案例可能需要更復雜的方法。特別是:

  • 如果您想根據(jù)用戶輸入更改 SQL 結構,參數(shù)化查詢不會有幫助,并且 mysql_real_escape_string 不包含所需的轉義。在這種情況下,您最好通過白名單傳遞用戶的輸入,以確保只允許“安全”值通過。
P粉283559033

無論您使用哪種數(shù)據(jù)庫,避免 SQL 注入攻擊的正確方法都是將數(shù)據(jù)與 SQL 分離,這樣數(shù)據(jù)仍然是數(shù)據(jù),并且 >永遠不會被 SQL 解析器解釋為命令。可以使用格式正確的數(shù)據(jù)部分創(chuàng)建 SQL 語句,但如果您完全不了解詳細信息,則應始終使用準備好的語句和參數(shù)化查詢。是與任何參數(shù)分開發(fā)送到數(shù)據(jù)庫服務器并由數(shù)據(jù)庫服務器解析的 SQL 語句。這樣攻擊者就不可能注入惡意SQL。

您基本上有兩種選擇來實現(xiàn)此目的:

  1. 使用PDO(用于任何支持的數(shù)據(jù)庫驅(qū)動程序):

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    $stmt->execute([ 'name' => $name ]);
    
    foreach ($stmt as $row) {
        // Do something with $row
    }
    
  2. 使用MySQLi(用于MySQL):
    從 PHP 8.2+ 開始,我們可以使用 execute_query() 在一個方法中準備、綁定參數(shù)并執(zhí)行 SQL 語句:

    $result = $db->execute_query('SELECT * FROM employees WHERE name = ?', [$name]);
     while ($row = $result->fetch_assoc()) {
         // Do something with $row
     }
    

    最高可達 PHP8.1:

     $stmt = $db->prepare('SELECT * FROM employees WHERE name = ?');
     $stmt->bind_param('s', $name); // 's' specifies the variable type => 'string'
     $stmt->execute();
     $result = $stmt->get_result();
     while ($row = $result->fetch_assoc()) {
         // Do something with $row
     }
    

如果您要連接到 MySQL 以外的數(shù)據(jù)庫,則可以參考特定于驅(qū)動程序的第二個選項(例如,pg_prepare()pg_execute() 對于 PostgreSQL)。 PDO 是通用選項。


正確設置連接

PDO

請注意,當使用PDO訪問MySQL數(shù)據(jù)庫時,真正的準備好的語句默認情況下不使用。要解決此問題,您必須禁用準備語句的模擬。使用 PDO 創(chuàng)建連接的示例是:

$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);

在上面的示例中,錯誤模式并不是絕對必要的,但建議添加它。這樣,PDO 將通過拋出 PDOException 的方式通知您所有 MySQL 錯誤。

但是,強制是第一行 setAttribute() 行,它告訴 PDO 禁用模擬準備好的語句并使用真實準備好的語句聲明。這可以確保語句和值在發(fā)送到 MySQL 服務器之前不會被 PHP 解析(讓可能的攻擊者沒有機會注入惡意 SQL)。

雖然您可以在構造函數(shù)的選項中設置字符集,但請務必注意,“較舊”版本的 PHP(5.3.6 之前)默默地忽略了 DSN 中的字符集參數(shù)

Mysqli

對于 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

說明

您傳遞給prepare的SQL語句由數(shù)據(jù)庫服務器解析和編譯。通過指定參數(shù)(? 或命名參數(shù),如上例中的 :name),您可以告訴數(shù)據(jù)庫引擎您要過濾的位置。然后,當您調(diào)用 execute 時,準備好的語句將與您指定的參數(shù)值結合起來。

這里重要的是參數(shù)值與編譯后的語句結合在一起,而不是 SQL 字符串。 SQL 注入的工作原理是在腳本創(chuàng)建要發(fā)送到數(shù)據(jù)庫的 SQL 時欺騙腳本包含惡意字符串。因此,通過將實際的 SQL 與參數(shù)分開發(fā)送,您可以限制最終出現(xiàn)意外情況的風險。

您在使用準備好的語句時發(fā)送的任何參數(shù)都將被視為字符串(盡管數(shù)據(jù)庫引擎可能會進行一些優(yōu)化,因此參數(shù)當然也可能最終被視為數(shù)字)。在上面的示例中,如果 $name 變量包含 'Sarah'; DELETE FROMEmployees 結果只是搜索字符串 "'Sarah'; DELETE FROMEmployees",并且最終不會得到 一個空表

使用準備好的語句的另一個好處是,如果您在同一個會話中多次執(zhí)行相同的語句,它只會被解析和編譯一次,從而提高速度。

哦,既然您詢問了如何進行插入,這里有一個示例(使用 PDO):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute([ 'column' => $unsafeValue ]);

準備好的語句可以用于動態(tài)查詢嗎?

雖然您仍然可以對查詢參數(shù)使用準備好的語句,但動態(tài)查詢本身的結構無法參數(shù)化,并且某些查詢功能也無法參數(shù)化。

對于這些特定場景,最好的辦法是使用白名單過濾器來限制可能的值。

// Value whitelist
// $dir can only be 'DESC', otherwise it will be 'ASC'
if (empty($dir) || $dir !== 'DESC') {
   $dir = 'ASC';
}
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板