考慮MySQL的列名只是一個very limited subset of characters(但請看到這個答案底部的編輯),你可以很容易地連接成的SQL字符串,而是先正則表達式刪除無效字符,如:
//use single quotes due to dollar sign
$column = preg_replace('/[a-z_-0-9$]/i','',$_POST['column']);
然後確保它裝在一個報價:
$column = ' `'.$column.'` ';
所以,你可以再做:
$sql = 'SELECT '.$column.' FROM users WHERE username=?';
然後把這個字符串放到你的綁定查詢中,這應該是完全安全的。
另外,在聲明的SELECT
一部分,你只需要刪除任何東西,是一個特殊字符,也就是*
,.
,空格和反引號operartor。
所以,你可以很容易地做到:
$column = preg_replace("/[*`.\s]/","",$_POST['column']);
這將意味着該查詢的SELECT部分只能有兩個WHERE
關鍵字等SELECT和濫用,這將導致查詢失敗(例如。)
順便說一句,給人以哪些列他們想打電話有很多潛力的陷阱,我沒有帶發現了它在野外很常見的一種選擇。爲什麼開發人員不清楚在選擇選項時要選擇哪些列?
編輯:您還可以使用擴展列名稱字符,這應該不會影響這種方法,但值得注意。但是,正如我上面所說的那樣,我認爲在99.999%的情況下,用戶不應該有能力命名列。
*「我不明白,如果它有可能獲得SQL從注入的‘選擇電子郵件’部分」 * - 不,不是,除非有一個'WHERE'條款(或任何其他類型的條款)使用輸入與用戶交互沒有準備。 –
理想情況下_whole_ select語句應該被參數化,所以這不應該發生。 –
*「想象電子郵件是可以破壞數據庫的字符串」* - 您需要用示例編輯您的問題。現在,「email」是「你」選擇的列,而不是用戶/輸入選擇的列。如果你完成了'SELECT $ email'並且用一個GET/POST數組定義了它並且沒有轉義它(注意:你不能綁定一個表/列),但是你可以用'real_escape_string()'來轉義它,或者使用安全列表,只是沒有準備好的聲明;那麼是的,如果你沒有,那可能(可能)擊中你。我會說我回答了這個問題;恕我直言。 –