2008/01/28

PHP avoid SQL Injection

SQL Injection 是一個寫 PHP 時大家常常忘掉的問題,但是一忘掉就會讓駭客有機可乘。

用 PHP 做登入時,SQL 語法大概會長這樣:
   select * from member where ID = '$USER_ID' and password = '$PASSWORD'


其中錢字號的是 PHP 的變數。登入時使用者填「test」、密碼填「123」,則 SQL 語法會變成下面這樣:
   select * from member where ID = 'test' and password = '123'


不過萬一有人要惡作劇,使用者填「test」、密碼填「' or ''='」,則 SQL 語法就會變成下面這樣:
  select * from member where ID = 'test' and password = '' or ''=''


看出來了嗎?如果把顏色去掉,最後一個判斷式是「or ''=''」,而這個判斷永遠會成立,所以即使前面沒有密碼也有資料會被列出來。這是最簡單的 SQL Injection,如果駭客心狠手辣的話,還能夠將機密資料列出、修改資料,甚至直接將資料庫刪除,所以不小心不行。如果有興趣的話可以參考以下相關網頁:

資安論壇 :: 觀看文章 - SQL Injection之解決建議措施及相關資訊彙整
http://forum.icst.org.tw/phpBB2/viewtopic.php?t=4376

SQL Injection WhitePaper
http://www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf

PHP 5 有提供 magic quote 會自動將單引號、雙引號加上反斜線,網路上也有寫好的程式可以使用,像是我之前寫的「PHP avoid SQL Injection 2」,但事實上這樣還是不夠的。

SQL 語法中,欄位的資料型態會有不同的語法,像說 SerialNumber = 123 和 UserName = 'zero',就有單引號的差別,如果 PHP 讀取欄位資料後沒有特別去注意資料型態,可能就會發生 SQL 語法中字串沒有使用引號的錯誤,丟出錯誤訊息一樣很危險。所以在開始使用變數時,最好做資料型態的轉換或是辨認,以免發生意想不到的狀況。

想要試試看自己的網頁有沒有上述的漏洞,可以使用 Parosproxy 這套漏洞檢測軟體做測試,他會再抓取所有可以使用的網頁連結以後,對每個網頁進行特定的檢測。

首先要先設定瀏覽器的 proxy 設定,讓瀏覽器透過 Paros 來上網,設定如下:



接下來把 Paros 啟動,然後讓瀏覽器瀏覽你準備要測試的網頁,這樣 Paros 就會抓到網頁位置,抓到以後就可以準備掃瞄。



在上面的清單中,選擇要掃瞄的網站以後,點選功能表的 Analyse -> Spider,抓取整個網站所有的超連結。



抓取後左下方應該會出現網站內的超連結列表,Paros 之後就針對這幾個連結進行漏洞測試。準備好開始測試後,點選 Analyse -> Scan 即可。



待掃瞄結束後,左下角 alert 頁籤中會顯示出你網站有漏洞的網頁,以及漏洞的類型,但是並不是有顯示就表示一定有漏洞,也不表示找不到漏洞就絕對安全,請自行判斷掃瞄結果。



掃瞄結束後,記得把瀏覽器的 proxy 設定改回來,不然 Paros 關掉以後就不能上網了。

2 則留言:

  1. 大約五六年前在某課堂上做過一篇SQL Injection的報告/示範,現在,在許多網頁上還能見到這種漏洞,這不知道要怪ASP/PHP...還是MSSQL/MySQL/PgSQL...?

    最大的漏洞,應該是"人"吧!

    回覆刪除
  2. MS SQL 據說還可以執行系統指令,蠻恐怖的。有時後安全和方便不會同時存在,所以還是寫程式的時候多注意一下比較好。

    防毒軟體什麼毒都防的了,就是防不了「心毒」 XD

    回覆刪除