2014-05-09 175 views
0

我被迫生成動態SQL。我意識到這樣做很複雜,下面的例子很愚蠢,顯然不需要動態SQL,只是用來說明這個問題。防止動態SQL中的SQL注入

轉義用戶提供的數據是不夠的,下面的腳本中的第三個查詢對SQL注入是可疑的。

我發現設計應用程序通常是最容易的,以便所有用戶輸入都是整數,並且只需使用(int)$_POST['user_input']對輸入進行類型轉換。

我現在需要將user_input設置爲文本。我應該如何防止SQL注入?一個選項是PHP的ctype_alpha(),但是,我不希望「用戶,輸入」結果爲FALSE,但應該保持原樣或轉換爲「userinput」(對於我來說scenerio是好的)。我正在考慮像$user_input= preg_replace('/[^a-z0-9,]/i', '', $_POST['user_input']);。這將是100%安全嗎?

編輯

注意,我不執行下面的查詢,但它插入到數據庫中,因此,準備語句不appliable。您可能認爲不應該使用動態SQL生成,但告訴我使用預準備語句是不正確的。

<?php 
$id=123; 
$query='SELECT * FROM someTable WHERE someColumn="'.$_POST['user_input'].'"'; 
$sql='INSERT INTO meta_table (id,sql) VALUES (?,?)'; 
$stmt=db::db()->prepare($sql); 
$stmt->execute(array($id,$query)); 

$sql='SELECT sql FROM meta_table WHERE id=123'; 
$stmt = db::db()->exec($sql); 
$query=$stmt->fetchColumn(); 

$stmt = db::db()->exec($query); //Prone to SQL Injection 
$rs=$stmt->fetchColumn(); 
?> 
+1

雖然對於*真*動態SQL這是一項相當複雜的任務,我在你的查詢中看不到任何動態的東西。 –

+0

@YourCommonSense。是的,我知道這個例子是學術性的,只是作爲一個愚蠢的例子。 – user1032531

+0

沒關係,你的學術答案也是 –

回答

4

阿哈哈,那太棒了!
最後,我設法瞭解什麼做這個傢伙意味着在他的「動態SQL」。難怪,因爲它是完美的僞裝,看起來像普通的SQL在第一眼和第二眼!

這裏回答:

不要這樣做。永遠。

您對「動態」SQL的想法本質上是錯誤的。沒有人這樣做。

我不知道您的具體任務,但您的解決方案顯然是錯誤。而且確實有一個理智的方法來做到這一點。只要遵循這些簡單的規則:

  • 擺脫meta_table
  • 擺脫存儲在數據庫
  • 寫SQL查詢(或建立)在應用程序中所有的疑問從只有兩個來源:
    • 硬編碼SQL,預先寫好的代碼中的
    • 準備好的發言所有的變量部分

並且讓你所有的SQL都完全安全

+0

啊,適用答案。謝謝。我的應用程序允許用戶選擇要顯示哪些列,使用哪些過濾器(即WHERE子句),是否對某些事物進行分組等。根據他們的選擇,有時需要連接其他表。是的,這很複雜。我正在嘗試確定如何在不使用惡意動態SQL的情況下執行此操作。你有沒有遇到過關於這個主題的任何白皮書? – user1032531

+0

看來你應該首先嚐試一些查詢生成器。 –

+0

查詢生成器?聽起來像是一樣的東西,但是有人建造它並在其周圍包裝一個類。知道一個好的?也許http://laravel.com/docs/queries? – user1032531