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

Wie kann man SQL-Injection-Angriffe in PHP verhindern?
P粉939473759
P粉939473759 2023-08-22 10:23:01
0
2
686
<p>Wenn Benutzereingaben unver?ndert in eine SQL-Abfrage eingefügt werden, wird die Anwendung anf?llig für SQL-Injection-Angriffe, wie im folgenden Beispiel: </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>Das liegt daran, dass der Benutzer etwas wie <code>value');DROP TABLE table;--</code> eingeben kann. <pre class="brush:php;toolbar:false;">INSERT INTO `table` (`column`) VALUES('value');--')</pre> <p>Wie kann ich das verhindern? </p>
P粉939473759
P粉939473759

Antworte allen(2)
P粉891237912

要使用參數(shù)化查詢(xún),您需要使用Mysqli或PDO。要使用mysqli重寫(xiě)您的示例,我們需要類(lèi)似以下的代碼。

<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("服務(wù)器", "用戶名", "密碼", "數(shù)據(jù)庫(kù)名稱(chēng)");

$variable = $_POST["user-input"];
$stmt = $mysqli->prepare("INSERT INTO 表名 (列名) VALUES (?)");
// "s"表示數(shù)據(jù)庫(kù)期望一個(gè)字符串
$stmt->bind_param("s", $variable);
$stmt->execute();

您可能需要閱讀的關(guān)鍵函數(shù)是mysqli::prepare。

此外,正如其他人建議的那樣,您可能會(huì)發(fā)現(xiàn)使用PDO等更高級(jí)的抽象層會(huì)更有用/更容易。

請(qǐng)注意,您提到的情況相當(dāng)簡(jiǎn)單,更復(fù)雜的情況可能需要更復(fù)雜的方法。特別是:

  • 如果您想根據(jù)用戶輸入更改SQL的結(jié)構(gòu),參數(shù)化查詢(xún)將無(wú)法幫助您,并且所需的轉(zhuǎn)義不包含在mysql_real_escape_string中。在這種情況下,最好將用戶的輸入通過(guò)白名單傳遞,以確保只允許通過(guò)“安全”值。
P粉771233336

無(wú)論您使用哪個(gè)數(shù)據(jù)庫(kù),避免SQL注入攻擊的正確方法是將數(shù)據(jù)與SQL分離,使數(shù)據(jù)保持?jǐn)?shù)據(jù)的形式,永遠(yuǎn)不會(huì)被SQL解析器解釋為命令。可以創(chuàng)建帶有正確格式化數(shù)據(jù)部分的SQL語(yǔ)句,但如果您不完全了解細(xì)節(jié),您應(yīng)該始終使用預(yù)處理語(yǔ)句和參數(shù)化查詢(xún)。這些是將SQL語(yǔ)句與任何參數(shù)分開(kāi)發(fā)送并由數(shù)據(jù)庫(kù)服務(wù)器分析的SQL語(yǔ)句。這樣,攻擊者就無(wú)法注入惡意SQL。

基本上有兩種方法可以實(shí)現(xiàn)這一點(diǎn):

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

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    $stmt->execute([ 'name' => $name ]);
    
    foreach ($stmt as $row) {
        // 對(duì)$row進(jìn)行操作
    }
    
  2. 使用MySQLi(適用于MySQL):
    自PHP 8.2+以來(lái),我們可以使用execute_query()方法來(lái)準(zhǔn)備、綁定參數(shù)和執(zhí)行SQL語(yǔ)句:

    $result = $db->execute_query('SELECT * FROM employees WHERE name = ?', [$name]);
     while ($row = $result->fetch_assoc()) {
         // 對(duì)$row進(jìn)行操作
     }
    

    在PHP8.1之前:

     $stmt = $db->prepare('SELECT * FROM employees WHERE name = ?');
     $stmt->bind_param('s', $name); // 's'指定變量類(lèi)型 => 'string'
     $stmt->execute();
     $result = $stmt->get_result();
     while ($row = $result->fetch_assoc()) {
         // 對(duì)$row進(jìn)行操作
     }
    

如果您連接的是MySQL以外的數(shù)據(jù)庫(kù),可以參考特定于驅(qū)動(dòng)程序的第二個(gè)選項(xiàng)(例如,對(duì)于PostgreSQL,可以使用pg_prepare()pg_execute())。PDO是通用選項(xiàng)。


正確設(shè)置連接

PDO

請(qǐng)注意,當(dāng)使用PDO訪問(wèn)MySQL數(shù)據(jù)庫(kù)時(shí),默認(rèn)情況下不會(huì)使用真正的預(yù)處理語(yǔ)句。為了解決這個(gè)問(wèn)題,您需要禁用預(yù)處理語(yǔ)句的模擬。以下是使用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);

在上面的示例中,錯(cuò)誤模式并不是嚴(yán)格必需的,但建議添加它。這樣PDO將通過(guò)拋出PDOException來(lái)通知您所有的MySQL錯(cuò)誤。

然而,必須的是第一行setAttribute(),它告訴PDO禁用模擬的預(yù)處理語(yǔ)句并使用真正的預(yù)處理語(yǔ)句。這樣確保語(yǔ)句和值在發(fā)送到MySQL服務(wù)器之前不會(huì)由PHP解析(使?jié)撛诘墓粽邿o(wú)法注入惡意SQL)。

雖然您可以在構(gòu)造函數(shù)的選項(xiàng)中設(shè)置charset,但需要注意的是,“舊版”P(pán)HP(5.3.6之前)在DSN中靜默忽略了charset參數(shù)。

Mysqli

對(duì)于mysqli,我們需要遵循相同的例程:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // 錯(cuò)誤報(bào)告
$dbConnection = new mysqli('127.0.0.1', 'username', 'password', 'test');
$dbConnection->set_charset('utf8mb4'); // 字符集

解釋

您傳遞給prepare的SQL語(yǔ)句由數(shù)據(jù)庫(kù)服務(wù)器解析和編譯。通過(guò)指定參數(shù)(在上面的示例中,可以是?或命名參數(shù),如:name),您告訴數(shù)據(jù)庫(kù)引擎您要在哪里進(jìn)行過(guò)濾。然后,當(dāng)您調(diào)用execute時(shí),準(zhǔn)備好的語(yǔ)句將與指定的參數(shù)值組合。

這里重要的是參數(shù)值與編譯后的語(yǔ)句組合,而不是與SQL字符串組合。SQL注入是通過(guò)欺騙腳本在創(chuàng)建要發(fā)送到數(shù)據(jù)庫(kù)的SQL時(shí)包含惡意字符串來(lái)工作的。因此,通過(guò)將實(shí)際的SQL與參數(shù)分開(kāi)發(fā)送,可以限制意外結(jié)果的風(fēng)險(xiǎn)。

使用預(yù)處理語(yǔ)句發(fā)送的任何參數(shù)都將被視為字符串(盡管數(shù)據(jù)庫(kù)引擎可能會(huì)對(duì)參數(shù)進(jìn)行一些優(yōu)化,因此參數(shù)最終可能是數(shù)字)。在上面的示例中,如果$name變量包含'Sarah'; DELETE FROM employees,結(jié)果將僅是搜索字符串"'Sarah'; DELETE FROM employees",您將不會(huì)得到一個(gè)空表

使用預(yù)處理語(yǔ)句的另一個(gè)好處是,如果在同一會(huì)話中多次執(zhí)行相同的語(yǔ)句,它只會(huì)被解析和編譯一次,從而提高一些速度。

哦,既然您問(wèn)到如何對(duì)插入進(jìn)行操作,這里是一個(gè)示例(使用PDO):

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

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

預(yù)處理語(yǔ)句是否適用于動(dòng)態(tài)查詢(xún)?

雖然您仍然可以對(duì)查詢(xún)參數(shù)使用預(yù)處理語(yǔ)句,但動(dòng)態(tài)查詢(xún)本身的結(jié)構(gòu)無(wú)法進(jìn)行參數(shù)化,并且某些查詢(xún)功能也無(wú)法進(jìn)行參數(shù)化。

對(duì)于這些特定的場(chǎng)景,最好的做法是使用白名單過(guò)濾器來(lái)限制可能的值。

// 值白名單
// $dir只能是'DESC',否則將為'ASC'
if (empty($dir) || $dir !== 'DESC') {
   $dir = 'ASC';
}
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage