2011-05-12 31 views
1

我只是讓我的一位朋友看看我用來從我的數據庫獲取數據的一些代碼,他告訴我這是非常不安全的,SQL注入是嚴重的事情。爲什麼這個SQL代碼不安全?

這是我現在使用的代碼:

$id = $_GET['id']; 
$result = mysql_query("SELECT * FROM news WHERE id = $id") or die("err0r"); 

他告訴我說,解決的辦法就是改變代碼爲:(根據我的朋友),使

$id = intval($_GET['id']); 
$result = mysql_query("SELECT * FROM news WHERE id = $id") or die("err0r"); 

我的代碼以某種方式任何能夠編輯我的數據庫中的內容的用戶:

http://mydomain.com/?p=news&id=38;DROP TABLE tablename; 

有人可以解釋他的確切含義嗎?

謝謝你,有一個愉快的一天

+0

看看這裏:http://stackoverflow.com/questions/332365/xkcd-sql-injection-please-explain – Swati 2011-05-12 15:54:08

回答

3

考慮會發生什麼,如果有人張貼PHP的http://www.mydomain.com?id=1; DROP TABLE news

舊版本試圖通過自動轉義所有的輸入變量自動防止這樣的事情;即通過向輸入中的任何引號字符添加斜線,以便它們不會破壞SQL查詢。這不再是當前PHP版本的默認設置,因爲它導致了很多其他問題。

不過你的情況,你還沒有引用變量在SQL查詢,因此,即使這種保護就不會幫你,因爲黑客不會需要包括任何報價砍你。

intval()解決方案確實可以幫助你解決這個問題,但它對其他問題(如你需要處理一個字符串變量)沒有幫助。

正確的解決辦法:

  1. 您應該使用mysql_real_escape_string()功能上是要傳遞到SQL查詢中的所有變量,以防止任何可能的黑客攻擊,就像這樣:

    $escaped_id = mysql_real_escape_string($id); 
    
  2. 您應該將引號中的所有變量放在SQL字符串中,如下所示:

    $result = mysql_query("SELECT * FROM news WHERE id = '$escaped_id'"); 
    

順便說一句... This comic strip是鏈接到演示問題非常流行的東西。 ;-)

+0

我要試試這個,好像你知道你正在談論=)感謝的人是什麼。 – MstrQKN 2011-05-12 16:19:44

+0

mysql_real_escape_string是一個良好的開端,但它有問題,可能不應該使用。更多在這裏:http://stackoverflow.com/questions/5414731/are-mysql-real-escape-string-and-mysql-escape-string-sufficient-for-app-secur – 2011-05-12 16:34:16

+0

@Grim - 的確,但實際* *解決方案(重寫使用不同的DB庫,如PDO整個應用程序)可能太大的飛躍,被提示了這個問題。 – Spudley 2011-05-12 17:36:37

4

如果你不試圖迫使id爲整數,什麼事情都可能你的數據庫上運行。例如,命令爲DROP TABLE。當然,有人仍然可以嘗試在這裏強制使用一個非常大的整數並導致溢出,如果這樣做不會導致比較小的錯誤。

看到這裏:http://xkcd.com/327/爲經典的例證。

順便說一句,如果你建立了一個測試服務器,你可以看到什麼真正與您的代碼,如果你導航到URL http://mydomain.com/?p=news&id=38;DROP TABLE tablename;

+0

沒什麼不好 - 但這並不意味着它不是一件重要的事情做。 – 2011-05-12 15:58:29

-1

它確保$ ID是一個數字發生。

3

該URL會使$ id = '38; DROP TABLE表名;' 第一個分號將結束當前查詢,導致第二個分號運行 - 這將丟棄您的表。

維基百科有一個很好的解釋:http://en.wikipedia.org/wiki/SQL_injection

至於做這個的:http://xkcd.com/327/ =]

你也應該開始思考,當你需要輸入不是一個數字,你會做什麼,所以INTVAL將無濟於事。有一個功能來對你的輸入進行sanatize總是方便 - 只是不要忘記使用它,並且永遠不要相信任何東西!

4

如果你不驗證「id」並確保它是一個整數,那麼有人可以將id設置爲(比如說)「1; drop table news;」它將按原樣發送到數據庫,並可能刪除「新聞」表。如果你做了驗證,以確保id是一個整數,你應該沒問題。此外,作爲預防措施的附加級別,您可能希望確保腳本使用的數據庫用戶僅具有完成需要的確切級別的權限 - 僅此而已。例如,如果您的程序無意刪除表,請確保數據庫用戶沒有此權限。