我很納悶…怎麼一堆 PHP 程式設計師不知道要怎麼防 SQL Injection
從 5 月份到 6 月份這段期間面試了好多個 PHP 程式設計師 , 包括也曾開職缺面試資訊主管
我都會問一個問題 , SQL Injection 怎麼防 ?
我說真的 , 大概面試了 10 來位 , 沒有一個人能夠脫口而出 , 不知道 SQL Injection 的程式設計師不會就算了 , 知道的人居然沒有一個人知道 PHP 原本就有功能可以過濾掉特殊字元 , 甚至還會回答用 str_replace 方法來過濾 , 所以我很想給看到這篇的人知道
如果你是用 mysql function , 那就是用 mysql_real_escape_string 去過濾
如果你是用 PDO , 就是用 bind value 作法
例如
1 2 3 4 5 | $sql = "SELECT * FROM users WHERE user_id=?"; $sth = $pdo->prepare($sql); $sth->execute( array($user_id) ); |
其實我是已經受夠了 !! 不知道是台灣的書籍太爛 , 還是學校裡面老師教的太爛 , 這種最簡單的防止方式居然都沒人知道 ?
舉個 PHP 原文上的例子
1 2 3 4 5 6 7 8 9 10 11 12 | <?php // Query database to check if there are any matching users $query = "SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'"; mysql_query($query); // We didn't check $_POST['password'], it could be anything the user wanted! For example: $_POST['username'] = 'aidan'; $_POST['password'] = "' OR ''='"; // This means the query sent to MySQL would be: echo $query; ?> |
上面的程式 , 會輸出
1 | SELECT * FROM users WHERE user='aidan' AND password='' OR ''='' |
那麼根本不用密碼就可以登入了 , 非常簡單的攻擊方式但卻又不得不重視 , 其實這種文字填空遊戲就是 SQL Injection ,
如果狠一點 , 還可以 DROP TABLE !!
是那個programmer 要不要自已去注意的問題
不是書太爛 XD
資料網路一堆
我印象中 mysql 新版的 都可以自動過濾這種問題了
不用特別寫程序去過慮了吧??
@kemper
如果有的話可否提供一些經驗讓我學習學習呢
這種knowledege,看過、學過就會了. 找人才的重點還是在他的理解、應變能力好不好.
我是覺得這應該是基本常識而非知識 ~
通常連這種常識都不知道的 , 可以想像得出他過去所做過的網站怎麼死的恐怕自己也不知道
就好比有些人拿 cookie 來檢查登入認證 ,而不是用 Session 一樣
說穿了就是經驗不足沒有深入 Web 程式概念 , 但我沒時間去教 , 我不曉得還有多少常識應該要知道的而不知道 , 所以我只問這題最重要 , 畢竟這簡單的常識不足會嚴重到讓資料庫整個被刪了
你好,我有些與prepared statement的問題想請教
http://php.net/manual/en/pdo.prepared-statements.php
提及到以下一句(請留意括號內的句子)
The parameters to prepared statements don’t need to be quoted; the driver automatically handles this. If an application exclusively uses prepared statements, the developer can be sure that no SQL injection will occur (however, if other portions of the query are being built up with unescaped input, SQL injection is still possible).
那不是指閣下依然要使用addslashes,htmlspecialchars,等去 unescaped input嗎???
另外還有一問題
$sql = “SELECT * FROM users WHERE user_id=?”;
$sth = $pdo->prepare($sql);
$sth->execute( array(’100”101′,’102′);
在以上的program中,有沒有幫法return回閣下實際執行過的SQL呢?e.g.
SELECT * FROM users WHERE user_id=’100′
SELECT * FROM users WHERE user_id=’101′
SELECT * FROM users WHERE user_id=’102′
因為我希望記錄所有執行過的SQL
@Pong
這和 PHP 的發展歷史有關係
早期 php 會預設將 FORM input 變數自動作 addslashes
但後期 php 預設是關閉的
而塞入 mysql 也不建議用 addslashes
例如 big5 編碼 又或者是用 MSSQL , 用 addslashes 都會有問題
所以 php 有提供各種 db 版本的 escape funcrtion
還有
你上面的 SQL , 會執行錯誤 , prepare 不是這麼用的
應該是
SELECT * FORM users WHERE user_id =? OR user_id =? OR user_id =?
這樣才會符合你輸入的陣列
當然
你可以用 SELECT * FROM users WHERE user_id IN ( $arr ) 的語法更直覺
但 $arr 部分要自己處理 ‘100′,’101′,’102′
你說的要記錄執行的 Query , PDO 目前我沒看到有任何指令可抓取最後一次的 QUERY
那個可能要自己寫了 , 目前沒看到 pdo 有類似 mysql_info() 這功能哩
那麼意思是使用escape function來取替addslashes,而htmlspecialchars則看自己需要來決定是否加上,對嗎?
假如我使用PDO,但不使用prepare statement,那麼該如何escape string呢?因為php好像沒有為PDO提供類似的function
假如我需要執行一句SQL(我覺實際情況大部份時間也只會執行一句SQL一次,很少會執行數次),那麼該用prepare statement嗎?因為直接執行
$count = $dbh->exec(”DELETE FROM fruit WHERE colour = ‘red’”);
看起來較簡單及快捷
正如你舉的例子,假如我堅持使用IN , 而$arr的element不是3個是300個,當中部份是有SQL injection的機會,哪麼如何使用prepare statement去解決此問題呢??
SELECT * FROM users WHERE user_id IN ( $arr )
$arr(”100″,”101″,”102″,……………”‘ OR ”=’”);
http://tw2.php.net/manual/en/pdo.quote.php
PDO 有個 quote() 可以用
現在台灣的程式設計師對Information Security相關知識明顯不足,這可能是台灣針對這一塊不夠重視,不管是教育界或是業界甚至政府單位都一樣,往往都在出事後才亡羊補牢,有些甚至不理,網站被植入back door也就算了,還被掛馬,增加使用者的安全隱憂與不便。
小弟認為,要學程式設計之前要先稍為專研資訊安全,而資訊安全這部分在學校的相關科系就應該列為必修。想當年小弟在混資訊工程的時候,等到大三才等到有老師開資訊安全的課程,而且還是選修,雖然那時候是抱著想噹老師的心態去上的,畢竟從高中就在玩SQL Injection,想試試自己在這方面的程度在哪,好笑的是,沒噹到老師,反而跟老師聊開了0.0。
剛好回想到,大三的時候有在台中某科技公司當實習生,剛去沒幾天又跟老闆聊開了,老闆知道我有在搞資安,說好聽一點是搞資安,說難聽一點是搞hacker (不是cracker喔!別誤會了!0.0),所以每次跟我聊天都會跟我說,不要一直搞資安了,多花點心思在程式設計上,資安是常時間研究的東西,並非一蹴可幾的,現在想想也是啦,當初就是搞得太入迷,偵九隊才找我去泡茶 = =a。
資訊安全這東西太廣了,從系統安全、網路安全、漏洞分析、加解密、等…太多太多了,實在是學不完,而學這些東西都是應用在預防的動作,對於事後的應變與處理也十分重要,沒有人敢說他的系統100%安全,連NASA、FBI都一樣,所以不管是IDS、IPS、漏洞分析諸如此類能做的盡量做,不幸被入侵了也能在最短的時間內檢查主機、修補漏洞並馬上恢復運作降低損失,且保留所有Log以利進行法律程序,對企業或政府來說這才是一個理想的程式設計師(MIS可能要改行了0.0)。
防SQL注入的方法有很多,可從PHP環境設定來達到或自己套個Filter,也可使用PHP函數來達到,如pigo大哥所說的mysql_escape_string、mysql_real_escape_string、prepare+execute(PDO)。
以登入表單來說,小弟防注入的方法是:username就限制只可用英文與數字,password直接做MD5加密儲存與比對,這樣就不會有SQL注入的問題了,且密碼有絕對的隱密性。
by the way~
請問pigo大哥,方便說出貴公司的名稱與地址嗎?想去應徵面試看看,小弟剛大學畢業沒多久,在程式設計方面還算新手,希望有機會可以多多請教前輩們,偷學幾招,呵呵!
上述內容若有不妥之處或造成您反感的地方請見諒,小弟只是說出自己的想法,也請多多指教!
@derek
我還想你介紹我公司咧 ! 哈哈
不過還是要說一下
就算帳密有加密 , 只要網頁上任何一個地方沒做好 sql string escape
用 sql injection 都可以抓取或修改想要的資料 , 即便是有加密的會員密碼
透過 sql injection , 就可以下兩段以上程式碼進而修改資料 , 改為自己的密碼 , 這些都是輕而易舉
drop table , drop database 那些都小 case 啦 , 駭客的目的應該不是要搞死你的網站
但可能從漏洞中放一些有的沒的當跳板 , 例如 javascript , 然後你的網站就等同一個攻擊別人的跳板
@pigo
當然,如pigo大哥所說,這是不可否認的,所以我才說入侵檢測、漏洞分析等等…都不可省
還有一個常見的是XSS攻擊,XSS是不可輕忽的一種攻擊手法,方法簡單但傷害很大
幾分鐘就可弄掛好幾個站,之前國外知名BSP服務「Myspce」就是被XSS搞掛的,受害用戶高達數百萬
這裡小弟提供一個小偏方,也算是免費的漏洞分析,網頁設計師可嘗試看看:
當設計好一個系統後,這時你就可以把站架起來弄個IP或網址,貼到對岸、日本、美國、德國知名的hacker網站,自然就有手癢的民眾幫你做漏洞分析了,呵呵,不過要小心遇到大尾的hacker,到時連log都沒得看0.0!
對了,這句「我還想你介紹我公司咧 ! 」~ 是說叫小弟幫你們公司宣傳嗎?呵呵!
可以參考看看這樣寫…前幾天剛好有人問…
http://www.timteam.org/?TIM=FORUM&FORUM=1&ShowDocument=15008#TIM15008
@小企鵝
哇 ! 你真有追根究柢的精神~ 不過沒做成 PHP FUNCTION 很可惜
但其實很多第三方的如 ADODB 或很多 MVC Framework 的 DB 類別都可抓出最後一次 Query 的 string 啦
而且也都有類似 bind value 作法都很方便實用
也許直接用第三方的會比較好做吧
但有一招是可以試試看啦 , 就是自己繼承 PDO 和 PDOStatement , 下面有簡單說明繼承方式
http://www.php.net/manual/en/book.pdo.php#73568
http://www.php.net/manual/en/book.pdo.php#73318
用繼承的方式 , 再重寫相關 method , 就可以自行記錄 sql string 及 bindvalue
然後可以自己多寫個 getLastQueryString() 出來組合成最後的 SQL String
我覺得!不應該用這種方式,面試一個程式設計師程度;並不是所有的RD領域都是在資安上面;SQL Injection很早之前就有人在研究,方法解決網路上可以找到很多,而且我相信只要肯學,這種問題不會不能解決;我相信台灣還是有很多了不起的人才;你沒有遇到表示你緣份不夠,這樣測試顯的不夠客觀吧!
我也有遇到學歷只有高中畢業,不過寫出來的程式面面俱到
@JOBE
我想這和程度也ˊ無關係 , 是經驗問題 , 我是要找有經驗的 , 所以出此問題研判此人經驗 , 當然這只是其中一題
我會用此題來判斷這個人的經驗 , 可能您不曉得我所遇到的人有過 1 年以上的經驗的都不ˋ知道
無經驗的新手也就算了
如果 1 年以上的都不曉得 SQL Injection , 那他過去的主管恐怕也不care 這回事情 , 又或者是只是照著書本做簡單的網站 , 但我不要找的人是只有簡單的經驗 , 我要找來的可以是獨立作業的
另外 SQL Injection 是資安問題 , 但確是 RD 程式沒有注意到所造成的問題 , 根本的源頭是在 RD
話說 ,SQL Injection 基本防治很簡單啊 , 這和肯不肯學也無關係 , 我主要是用這題當作研判一個 RD 過去做的網站夠不夠大 , 遇到的問題多不多而已
那也跟台灣教育沒什麼關係吧!不用拿台灣書籍跟教育來說教的不夠吧!
師父領進門修行在個人!很多東西都是出了社會,才會學的到!
那如果你只是要測試他作過的網站夠不夠大,我以前應徵RD的經驗給你作參考,叫他秀作品給你看,針對他的作品提出問題,順便問問他,有規劃過SA或SD嗎?
有些人一輩子都在作AP系統的開發,如果只是要作內部AP系統的話,就不太需要了解SQL Injection;當然人家如果還沒來面試時,你就問你是作那些方面的RD;也可節省您的時間,跟他的時間!
你也不用常說面試不到對的人;可能你也不知道有些有經驗的人,也會被自己的經驗害死!
@JOBE
台灣的教育好不好是見人見智 , 所謂上梁不正下梁歪 , 上面的教育制度 , 師資怎樣 , 學生素質如何
大學的錄取率如何大家清楚得很
企業內的主管是不是也重視這問題 , 是否有好好帶 RD 是不是都是個問題 ?
而且我是抒發個人心情嘛 … 何必看那麼嚴重呢 , 我只是將我所見的說出來
寫這篇的本意 , 仍是要讓看到的人知道 sql injection 是很嚴重的資安問題
站在格局較高來看 , 讓有看到的人心生警惕就是我的目的
批判只是附帶的 , 發洩心中對教育失敗的不爽 , 對資安重視的程度太低
所以才會有很多 RD 連這個都不清楚 , 我不是怪罪辛苦的 RD 啦
順帶一提 , 很多RD主管自己根本不知道 sql injection , 所以他也不會要求下面的人去做
主管本身的素質就是上樑了 , 要等到問題出現的時候才來補洞 , 傷害已經造成
至少我上一家公司就是如此 我還去教我的主管咧 , 直接示範免帳密就把他之前做的系統登入了
當然補洞補的很辛苦 , 全部的程式都要補 , 因為是公開的網站所以有此感想是必然的
但不論是做內部或外部網站 , RD 或主管仍要秉持無欲則剛的原則 , 如果貪圖一時之快 , 內部的也會因為內部人員中木馬導致攻擊內部網站
這種後果若要追究起來源頭仍是 RD 設計的系統不良