2012-07-22 139 views
3

編輯如果你打算回答這個問題,請至少閱讀它。不要簡單地閱讀標題,然後Google'sql注入php',並粘貼結果作爲答案str_replace的這種用法足以防止SQL注入攻擊嗎?

首先,我很清楚,有很多的資源可用於如何最好地防止SQL注入,但我的問題具體是關於如果很少的努力就足夠了。

最近我跟一家合同組織聯繫,他們之前承包商開發的合作伙伴(PHP)網站被發現存在重大安全問題(我個人最喜歡的是在URL中使用字符串'Emergency'未經身份驗證訪問網站中的任何頁面...)

我被要求檢查一個PHP站點的安全性並突出顯示所有主要問題。我知道從這個網站以前的經驗,編碼的標準是真的很糟糕(例如,大量的代碼重複跨越5%的網頁代碼,數百個未使用的變量,$ var =「是」代替布爾值,編寫的SQL語句插入每個腳本,默認情況下不安全(某些頁面忘記驗證用戶身份)等)。審查網站是一個痛苦的提醒,世界上有一些真正的蠢蛋稱自己是開發者。

由於這些代碼質量問題,我只想強調嚴重和半嚴重的安全問題。如果我注意到網站的每一個問題,我的審查將花費數週時間。

我不是SQL注入方面的專家,但我的理解是,您必須必須能夠在注入任何其他類型的語句之前關閉現有查詢的帶引號的字符串。那麼下面這行代碼是否足夠?

"'".str_replace("'","''",$_POST['var_name'])."'" 

我沒有興趣在有關改善或更改代碼的建議,就是否有可能在這種情況下對通過$ _ POST [「VAR_NAME」] SQL注入。如果您不熟悉PHP str_replace確實將第一個參數的所有實例替換爲第二個參數,而不僅僅是第一個實例。

任何輸入非常讚賞。

+1

你可能想看看[這個答案](http://stackoverflow.com/questions/3115559/exploitable-php-functions/3697776# 3697776)@Rook – 2012-07-22 01:07:30

+1

我個人認爲最簡單的就是使用PDO。這可能意味着對代碼做了一些更改,但我認爲這是「最小的努力」,因爲只要您使用準備好的語句,就可以保證**免受SQL注入的影響。 http://php.net/manual/en/book.pdo.php http://www.php.net/manual/en/pdo.prepare.php – Raekye 2012-07-22 01:20:57

+0

湯姆,我愛你的問題,因爲它啓發了麥克麥金託什的答案,但對你的問題進行一些小調整將會闡明:假設代碼做了'''「.str_replace(array(」\\「,」'「),array(」\\\\「,」''「),$ _ POST [ 'var_name'])。「'」'(加倍反斜槓)? – 2013-04-29 22:29:37

回答

8

不是。誠實地說,如果你沒有準備好你的陳述,你是在尋求一個受到傷害的世界。

僅僅因爲你用引號逃避了你的引用,你並沒有保護自己。想想這個:

的用戶發送給您:username'; drop database foo;

你將難逃它作爲username''; drop database foo;

但是!如果用戶這樣做:username\'; drop database foo;

你會遇到麻煩。你將解決這個問題username\''; drop database foo;

這意味着用戶放置的引號被轉義,並且你的引用結束了字段用戶名。然後這個下降將被執行。這是非常不安全的。

您需要確保您準備好您的語句或應用quote命令,如PDO::quotemysqli_real_escape_string作爲這些轉義特殊字符。

+0

謝謝,這告訴我,我甚至沒有接近'想到盒子外面' – tomfumb 2012-07-22 01:54:38

+1

是的,所有涉及安全性的事情都需要至少從6個角度來看待。如果你沒有從頂部,前部,底部,左側,右側和後部看它,你甚至沒有看到第六個漏洞。 – 2012-07-22 01:56:47

+3

Fluttershy(她是最好的小馬)+1 +1 – 2012-07-23 15:37:35

1

您有兩個選擇 - 轉義unsafe_variable中的特殊字符或使用參數化查詢。

$safe_variable = mysql_real_escape_string($_POST["user-input"]); 


$mysqli = new mysqli("server", "username", "password", "database_name");  
$unsafe_variable = $_POST["user-input"]; 
$stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)"); 

兩者都可以保護您免受SQL注入。參數化查詢被認爲是更好的做法,但在變量中轉義字符將需要更少的更改。

+2

我強烈推薦以後。準備你的陳述可以使你免受傷害。 – 2012-07-22 01:35:24

0

要回答你的問題:不,只是刪除引號不足以防止SQL注入。

例如,

"SELECT * FROM user_table WHERE userid=$userid AND password=$password"

可以去嚴重錯誤,如果$password載 「垃圾或者1」,或者類似的東西。所以,如果他們有格式不正確的查詢,刪除引號將無濟於事。

0

這取決於您的數據庫服務器及其配置。

加倍'''是轉義字符串文字內容的ANSI標準方式,應該是就足夠了。但是,如果您在9.1之前使用MySQL或PostgreSQL版本,則缺省情況下,字符串文字語法不符合ANSI標準(如果重新配置,它可以是),並且反斜線字符具有特殊含義。這允許在680的答案中的\'這樣的攻擊。此外,如果您將字節字符串傳遞給您的數據訪問函數,並且您的數據庫恰好使用的是東亞字符編碼,則會出現str_replace'上執行字節替換的問題,這可能是是多字節序列的一部分,最後以高字節結尾,然後是'':第一個引號被作爲多字節序列的一部分被佔用,然後第二個引號關閉字符串。 (這在UTF-8中不會發生,該設計旨在避免拖尾低字節。)

對正在使用的數據庫使用適當的轉義呼叫(例如mysql_real_escape_string),或者更好地使用參數化查詢,意味着您不必知道這些晦澀難懂的邊緣案例。

0

這個怎麼樣數組字符串替換

$search = array(" ' ", ' " ', " ` ", ' & ', ' , ', ' ; ', ' SELECT ', ' WHERE ', ' AND ');