2012-10-14 52 views
4

我在php中使用PDO,因此無法使用預處理語句轉義表名或列名。下面是自己實現它的一個萬無一失的方法:安全地轉義表名/列名

$tn = str_replace('`', '', $_REQUEST['tn']); 
$column = str_replace('`', '', $_REQUEST['column']); 
$sql = "SELECT * FROM `tn ` WHERE `column` = 23"; 
print_r(
    $pdo->query($sql)->fetchAll() 
); 

還是還有一些可以攻擊的途徑嗎?

+0

@Petah不是一個選項 – qwertymk

+1

@Petah我需要能夠使用這個類後,我添加更多的表,而不必不斷更新白名單 – qwertymk

+1

祝你好運:) ... – Petah

回答

4

您可以通過詢問數據庫哪些列對於給定數據庫表格有效來使用動態白名單。這是一個額外的SQL查詢,但安全性很好。

select COLUMN_NAME 
from INFORMATION_SCHEMA.COLUMNS 
where TABLE_SCHEMA = :databaseName 
    and TABLE_NAME = :tableName 

獲取結果,然後確保所有動態列名都在結果集中。

我相信意見包含在INFORMATION_SCHEMA.COLUMNS,所以它應該只是簡單的工作。

然後,在組裝動態sql時(我假設你只使用ascii列名稱,否則你可能有其他注意事項),在驗證的列名稱周圍使用反引號。

+0

這將導致每次調用都有兩個數據庫調用。我正在尋找能夠清理表格和列名稱而不是白名單的東西。我真的想知道我可以通過的限制。例如我知道我可以通過'a-zA-Z0-9_.'離開。那麼其他的字符呢? – qwertymk

+3

除非你真的明白你在做什麼,包括一個良好的理解角色,否則你已經犯了錯誤(期間不允許,請參閱http://dev.mysql.com/doc/refman/5.0/en/identifiers.html)設置和unicode,只需使用白名單,並停止擔心你沒有的性能問題。或者,限制表名和列名的長度限制爲a-zA-Z0-9_,以便於驗證。避免unicode和非ascii字符。 – goat

+0

大家都在說,但爲什麼?如果我有這樣的事情會發生什麼(waitforitwaitforit):''''「。 preg_replace('#''| - #','',$ input)。 「'''''(兩個''表示一個) – qwertymk