目前我正在研究一個簡單工具的概念,以執行一些用PHP編寫的「維護」數據庫操作(drop/truncate/copy tables等)。PHP PDO:保護針對SQL注入的動態標識符
這必然要求SQL語句中的標識符是動態用戶輸入。儘管預處理語句對於任何比較值的SQL語句與用戶輸入的分離都是完美的,但它們並不意味着用於表名或列名等標識符。 (也就是說,I can't use準備了用於準備標識符的語句。)
保護動態標識符的常用方法是將白名單列入白名單,但這需要靜態和已知的數據庫結構。例如,我想執行一個像Copy table A and name it B
這樣的命令。這裏有趣的部分是B
。
假設用戶通過身份驗證並被允許執行此操作,如何防止SQL注入?這甚至有可能嗎?
我發現an approach這表明,在任何這樣的標識符簡單地引用重音符(`):
$table_name = 'origin_table'; // can be checked against existing tables
$copy_table_name = 'user_input';
$quoted_table_name = '`' . str_replace('`', '``', $copy_table_name) . '`';
$sql_statement = "CREATE TABLE {$quoted_table_name} LIKE {$table_name}";
那是一個足夠的保護,防止可能的SQL注入?
更新
PDO::quote()
(在回答中提到的)是不是一種選擇。它不會逃避重音符(`):
$user_input = 'table`; TRUNCATE TABLE users --';
var_dump($pdo->quote($user_input));
//string(33) "'table`; TRUNCATE TABLE users --'"
更新2 PostgreSQL的擴展具有的功能正是出於這個目的:https://secure.php.net/manual/en/function.pg-escape-identifier.php
是的,但只要完整的字符串被認爲是標識符,像'CHAR(96)'這樣的函數不會被MySQL解釋。 (編輯:我回答的評論已被刪除) – David
大聲思考:我會讓用戶在表單中輸入表格和列名。現在,這些可以驗證爲無意義的字符和代碼。然後可以很容易地檢查它們與'mysql數據字典'的匹配。任何不匹配,然後錯誤。我還會有一個表格和/或列的「白名單」。從提供的信息中生成所需的SQL是一項相當簡單的任務。即。想'查詢建設者'? –
@RyanVincent謝謝,我會處理這些問題。一個最佳的解決方案將是像'TableCopier :: copyTables($ src,$ dest)'這樣的方法。我肯定可以給這個方法寫一個評論:«不要讓它過分的價值!»。但是這並不能保護它不被使用,並在野外造成SQL漏洞。 – David