2011-08-28 57 views
1

在MySQL中是一個在SQL注入安全的存儲過程中的預備語句?見下面的例子。 get_info存儲過程傳遞一個表名(pTbl)和where子句(pWhere)。 p可以有許多AND(例如fld1 =「a」AND fld2 =「b」AND ...)。這可能不是最好的辦法,但我需要動態SQL。存儲過程中的預準備語句是否安全地使用SQL注入?

CREATE PROCEDURE get_info(pTbl VARCHAR(10), pWhere TEXT) 
BEGIN 
    SET @uSQL = CONCAT('SELECT info FROM ',pTbl,' WHERE ',pWhere); 
    PREPARE ps FROM @uSQL; 
    EXECUTE ps; 
END$$ 

我打過電話像下面使用MySQL查詢瀏覽器的存儲過程,但只得到了一個錯誤回話說我在SQL有語法錯誤。

CALL get_info('tbl','1=1;SELECT * FROM information_schema.TABLES;'); 

如果它幫助任何存儲過程正在使用PDO從PHP調用,如下所示。 $ tbl是$ _SESSION變量,$ whr是$ _GET變量。

$s=$c->prepare("CALL get_info(?,?)"); 
$s->execute(array($tbl,$whr)); 

該存儲過程是否安全?如果不是,我將如何注入它?如果我從MySQL查詢瀏覽器vs網頁注入,它有什麼不同嗎?謝謝...

+0

問題不完整;你沒有提及'$ tbl'和'$ whr'的來源。 –

+0

@Ignacio Vazquez-Abrams,$ tbl是$ _SESSION變量,$ whr是$ _GET變量。 – Txoov

+0

爲什麼爲此使用存儲過程,而不是在PHP中生成語句?您可以動態構建['WHERE'子句](http://stackoverflow.com/questions/327274/mysql-prepared-statements-with-a-variable-size-variable-list),並仍然使用用戶輸入參數,從而防止注射。 – outis

回答

1

任何時候你插入一個值到一個語句中有注入的可能性。該程序很脆弱。在SQL過程和函數中注入的唯一一般限制是PREPARE在單個語句上工作。在這種特定情況下,注入的文本在SELECT中的WHERE子句基本上限制對子選擇,UNION,調用過程和函數(棘手但可能非常危險)的攻擊以及轉儲到文件(如果get_info的定義器具有FILE特權)。

舉個例子,嘗試:

CALL get_info('tbl','1=0 UNION SELECT CONCAT(user, "@", host, " ", password) FROM mysql.user;'); 
+0

@Javier:甚至沒有在CONCAT()中? –

+0

@outis,你提供的例子確實奏效。謝謝。 – Txoov

+0

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_quote 在這種情況下也使用QUOTE()... – inf3rno

1

由於其中一個值來自用戶,所以有些形式的SQL注入是可能的;雖然只有SELECT查詢可以運行,但仍然可以通過將1=1傳遞給頁面來顯示信息。以這種方式顯示的信息的實際用處可能很低,但它仍然可能發生。

+0

感謝您的幫助。 – Txoov

2

是的,它是安全的。 (編輯:不,它不是)

關鍵是要知道SQL文本何時被分析並轉換爲語義樹。準備好的陳述恰恰是:準備好的陳述,只是等待論據。它們存儲在完全編譯爲內部執行計劃的服務器中,缺少參數的「漏洞」。

這就是爲什麼你會得到語法錯誤,你試圖將整個WHERE部分設置爲參數;但它是一個完整的表達式樹。準備好的陳述只能有數據元素的「漏洞」,而不能用於語法文本。

傳輸參數的協議完全是二進制安全的,無論你在參數變量中有什麼,它們都將作爲二進制數據發送並僅用作數據,而不是作爲SQL命令的一部分。

編輯 ooops!我剛剛注意到你做文本插值,只是不在PHP中,但在SQL中。這意味着您稍後使用外部數據構建S​​QL命令。

絕對不安全。

+0

我不認爲我們讀的是一樣的代碼然後... –

+0

@Javier,謝謝你的輸入。 – Txoov

相關問題