準備好的語句:它們可以處理參數化表名稱嗎?
本文解決了預處理語句是否可以有效處理參數化表名以防止 SQL 注入漏洞的關鍵問題。
問題:
直接將使用者提供的資料(包括表名)嵌入 SQL 查詢中是一個主要的安全風險。 考慮這個例子:
<code class="language-php">function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }</code>
如果 .$new_table.
未正確清理,串聯 $new_table
會使該函數容易受到 SQL 注入的攻擊。
嘗試參數化:
緩解此問題的常見嘗試是嘗試參數化表名稱:
<code class="language-php">function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }</code>
現實:
不幸的是,這種方法失敗了。 準備好的語句旨在防止運行時值注入,而不是防止更改SQL查詢本身的結構。 資料庫解析器將表名解釋為查詢結構的一部分,而不是執行時間參數。 用佔位符替換它會導致無效的 SQL。
即使系統提供預先準備語句模擬(例如 PDO),結果也將是無效查詢(例如,SELECT * FROM 'mytable'
而不是 SELECT * FROM mytable
)。
解:
處理使用者提供的表名時防止 SQL 注入的唯一可靠方法是採用嚴格的白名單。 這涉及預先定義允許的表名列表,並確保在查詢中使用之前對照此白名單檢查任何用戶提供的表名。 切勿直接使用使用者輸入來建構涉及表名的 SQL 查詢。
以上是準備好的語句可以處理參數化表名以防止 SQL 注入嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!