分享內容(
26人
首先要找出前端網頁中允許使用者輸入的部分,像是表單標籤<FORM>內允許輸入的欄位或選單部分,這些允許使用者輸入的部分,表示使用者可以自行決定要輸入的,正常的內容當然是最好,但也可能是超出允許範圍之外的內容,甚至是帶有惡意的程式碼,這通常也是嘗試入侵時會被利用的點。一般常見的例子像是使用者登入時的帳號密碼欄位等。此外,許多動態產生的連結URL也是容易被利用的輸入點,例如:http://www.example.com/query.php?qid=13313&uid=31331&page=2其中qid、uid、page都是有機會讓使用者修改輸入的輸入點,而在PHP中會以$_REQUEST、$_POST、$_GET等參數傳入網站應用系統,後續再處理與應用。
設變數接受輸入
一般來說,程式要使用外部輸入的資料時,要避免直接使用$_REQUEST、$_POST、$_GET這些原始輸入,較安全的方法通常是先設個變數接收,然後依據變數的用途,執行必要的檢查與過濾後再使用,如此一來,只要程式設計師養成好習慣,例如︰「不使用原始輸入資料」、「輸入資料過濾檢查後再使用」,效果就像在網路上部署防火牆一樣,能將外部資料與內部的資料處理流程區隔開來,並檢查與過濾進入內部的所有資料,符合條件者才准傳入。這是建立「輸入驗證」防線的基礎原則。
限制輸入環境
輸入環境的限制是一種避免出現非預期輸入的方法。如果有明確的輸入選項,就不要提供文字輸入欄位,例如性別在絕大部分情況下,只有「男」與「女」兩個選擇,就不要提供使用者有輸入「石頭」的機會;一年不會超過12個月,每個月都有固定的天數,這些最好都做成選單讓使用者選擇。
就算不是選項型態,多半也有固定的格式,也因此會有固定的條件限制,例如信用卡號碼為16碼的數字,就不會有英文、數字混雜的情況;像身份證字號本身有特定的編碼方式,也可以使用公式驗證;電子郵件帳號一定要「@」,這些都是很實際的例子。
利用白名單選項,也是一種做法。限制輸入的可能性,或限制輸入的格式、型態、長度、內容等,只要條件越明確,就越能避免有非預期的輸入。通常網頁程式設計師會利用JavaScript與正規表示式(Regular Expression)預先檢查輸入的內容,不過,JavaScript的限制功能多半很容易就被繞過或是關閉,只能「防君子不防小人」,還是要在伺服器端對這些輸入再驗證一次,比較保險。
在輸入過濾檢查工作前,仍需要先瞭解資料要輸入的環境,例如會在哪些環境下使用,這樣才知道後面需要設定什麼過濾檢查的條件。舉例來說,如果我們知道變數$var將要傳入SQL語法中當作關鍵字查詢,我們才會知道除了要檢查與過濾$var內容的合理性之外,還需要考慮$var在SQL語法中的限制,這樣對$var的過濾檢查才會完整;如果$var會傳進system(),作為Linux執行指令的一部份,就要考慮$var會對Linux指令造成的影響而預先過濾,這時的過濾條件又跟之前用在SQL語法時是不同的。
防止SQL Injection大部分開發者都會應用 addslashes() 來防止SQL Injection的發生,但addslashes()只會過濾單引號(')、雙引號(")、反斜線 backslash(\) 以及空字元 NUL((the null byte,特殊攻擊仍有辦法跳過檢查。而php.ini中的magic_quotes_gpc選項雖然能夠在$_GET,$_POST,$_COOKIE這三種輸入執行過濾,但因為動作與addslashes()雷同,如前所述,一樣有被跳脫的疑慮。
所以,我們建議採用資料庫提供的過濾函式,譬如MySQL可以使用mysql_real_escape_string()濾除跳脫字元,也免除了針對每個輸入都加上過濾函式的繁瑣工作。
如果PHP程式中有呼叫系統指令,則可以使用escapeshellcmd()過濾Shell內的一些有意義的特殊字元,或是乾脆使用escapeshellarg(),將所有可能的輸入參數都濾除,這樣可以防止Command Injection的發生。
當輸入資料的用途是指出系統內的某個或某些檔案時,例如應用在require()、require_once()等,應該限制僅允許輸入檔名,將目錄寫死或設定絕對路徑,也可以將「../」這樣的目錄跳脫濾除,來避免Code Injection的問題。
輸出、輸入都要檢查,防XSS
內容輸出前,也需要進行過濾檢查,避免插入了非預期的網頁內容、修改網頁呈現,甚至插入惡意的JavaScript,也就是Cross-Site Scripting(XSS)。在PHP中可以使用htmlspecialchars()將 & > " < 轉成HTML字串格式,例如:
* & (和) 轉成 &
* " (雙引號) 轉成 "
* < (小於) 轉成 <
* > (大於) 轉成 >
這樣可以避免使用者的輸入中當有<IFRAME>、<SCRIPT>這些HTML標籤時會被瀏覽器當成網頁內容而執行。如果資料輸入時本就不允許輸入HTML標籤,不如直接在輸入檢查時,以strip_tag()直接濾掉,免除後患。
總而言之,完善的輸入驗證(Input Validation)可以預防大部分的網頁資安問題,而完善的輸出驗證(Output Validation)則可以防止OWASP 2007 Top 10排名第一的XSS攻擊。做好這些輸出入驗證工作,便可以有效強化PHP網頁程式的安全性。
設變數接受輸入
一般來說,程式要使用外部輸入的資料時,要避免直接使用$_REQUEST、$_POST、$_GET這些原始輸入,較安全的方法通常是先設個變數接收,然後依據變數的用途,執行必要的檢查與過濾後再使用,如此一來,只要程式設計師養成好習慣,例如︰「不使用原始輸入資料」、「輸入資料過濾檢查後再使用」,效果就像在網路上部署防火牆一樣,能將外部資料與內部的資料處理流程區隔開來,並檢查與過濾進入內部的所有資料,符合條件者才准傳入。這是建立「輸入驗證」防線的基礎原則。
限制輸入環境
輸入環境的限制是一種避免出現非預期輸入的方法。如果有明確的輸入選項,就不要提供文字輸入欄位,例如性別在絕大部分情況下,只有「男」與「女」兩個選擇,就不要提供使用者有輸入「石頭」的機會;一年不會超過12個月,每個月都有固定的天數,這些最好都做成選單讓使用者選擇。
就算不是選項型態,多半也有固定的格式,也因此會有固定的條件限制,例如信用卡號碼為16碼的數字,就不會有英文、數字混雜的情況;像身份證字號本身有特定的編碼方式,也可以使用公式驗證;電子郵件帳號一定要「@」,這些都是很實際的例子。
利用白名單選項,也是一種做法。限制輸入的可能性,或限制輸入的格式、型態、長度、內容等,只要條件越明確,就越能避免有非預期的輸入。通常網頁程式設計師會利用JavaScript與正規表示式(Regular Expression)預先檢查輸入的內容,不過,JavaScript的限制功能多半很容易就被繞過或是關閉,只能「防君子不防小人」,還是要在伺服器端對這些輸入再驗證一次,比較保險。
在輸入過濾檢查工作前,仍需要先瞭解資料要輸入的環境,例如會在哪些環境下使用,這樣才知道後面需要設定什麼過濾檢查的條件。舉例來說,如果我們知道變數$var將要傳入SQL語法中當作關鍵字查詢,我們才會知道除了要檢查與過濾$var內容的合理性之外,還需要考慮$var在SQL語法中的限制,這樣對$var的過濾檢查才會完整;如果$var會傳進system(),作為Linux執行指令的一部份,就要考慮$var會對Linux指令造成的影響而預先過濾,這時的過濾條件又跟之前用在SQL語法時是不同的。
防止SQL Injection大部分開發者都會應用 addslashes() 來防止SQL Injection的發生,但addslashes()只會過濾單引號(')、雙引號(")、反斜線 backslash(\) 以及空字元 NUL((the null byte,特殊攻擊仍有辦法跳過檢查。而php.ini中的magic_quotes_gpc選項雖然能夠在$_GET,$_POST,$_COOKIE這三種輸入執行過濾,但因為動作與addslashes()雷同,如前所述,一樣有被跳脫的疑慮。
所以,我們建議採用資料庫提供的過濾函式,譬如MySQL可以使用mysql_real_escape_string()濾除跳脫字元,也免除了針對每個輸入都加上過濾函式的繁瑣工作。
如果PHP程式中有呼叫系統指令,則可以使用escapeshellcmd()過濾Shell內的一些有意義的特殊字元,或是乾脆使用escapeshellarg(),將所有可能的輸入參數都濾除,這樣可以防止Command Injection的發生。
當輸入資料的用途是指出系統內的某個或某些檔案時,例如應用在require()、require_once()等,應該限制僅允許輸入檔名,將目錄寫死或設定絕對路徑,也可以將「../」這樣的目錄跳脫濾除,來避免Code Injection的問題。
輸出、輸入都要檢查,防XSS
內容輸出前,也需要進行過濾檢查,避免插入了非預期的網頁內容、修改網頁呈現,甚至插入惡意的JavaScript,也就是Cross-Site Scripting(XSS)。在PHP中可以使用htmlspecialchars()將 & > " < 轉成HTML字串格式,例如:
* & (和) 轉成 &
* " (雙引號) 轉成 "
* < (小於) 轉成 <
* > (大於) 轉成 >
這樣可以避免使用者的輸入中當有<IFRAME>、<SCRIPT>這些HTML標籤時會被瀏覽器當成網頁內容而執行。如果資料輸入時本就不允許輸入HTML標籤,不如直接在輸入檢查時,以strip_tag()直接濾掉,免除後患。
總而言之,完善的輸入驗證(Input Validation)可以預防大部分的網頁資安問題,而完善的輸出驗證(Output Validation)則可以防止OWASP 2007 Top 10排名第一的XSS攻擊。做好這些輸出入驗證工作,便可以有效強化PHP網頁程式的安全性。
參考資料:《iThome企業資安技術應用專刊》阿碼科技資安顧問陶靖霖
▼ ADVERTISEMENT ▼
廠商來幫忙
邦友收藏動態
- 三論專案的價格與成本 (ace33022)
- [Day 30]簡介軟體開發相關角色與UML產出模組-7 (ace33022)
- 如何在windos7的預覽窗格中預覽PDF (ace33022)
- 中國谷歌警告谷姐侵權 (chiehwen)
- 政府機房共構露曙光 (euros1002)
- 邁向eGov 2.0 優質網路政府 (euros1002)
- 顛覆傳統的新BI (euros1002)
- 政府廣發工商憑證,企業線上交易如何運用? (euros1002)
- 整合通訊也能DIY (euros1002)
- 如果購買W7 Ultimate 繁體中文版,想要確認若經由MUI轉換成日文介面,語音辨識功能是否就可以辨識日文? (mf0519)
- 5 本超優免費的自學 Linux 電子書 (scottchen)
- 常用網路管理工具 Getif (Get Interfaces)教學 (kaiin323)
- 6款Windows平臺免費備份工具 (tomtom123)
- 關於Cisco、linux、MySQL、Oracle、unix一些命令手冊 (fran633)
- 穩定的感覺會咬人 (heero1219248)
- 化繁為簡的工作拆解手法 (brgodman)
- 關於CCNA一些自我學習資料大全~! (51pass)
- 系統分析師必須思考的8個問題 (arnolin)
- 10 個不可或缺的 Linux/Unix 指令速查表 (scottchen)
- 用群組原則輕鬆管理使用者電腦 (raytracy)
安裝「收藏快捷鍵」,可以讓邦友直接透過Google工具列上的按扭,快速收藏站內、站外的網頁。
相關問答
- solar - Framework for PHP 5
- 學 .net 好還是學php好呢?
- 請問在Gentoo Linux上要怎麼加上PHP的ctype模組?
- 請問那一套PHP RSS parser比較好用?
- 不同預設閘道(Getway)時,檔案無法以php上傳
- 用「iProber探針」查詢PHP主機資訊 (租虛擬主機必備)
- 請推薦適合使用在PHP的Ajax框架?
- Zend Framework 1.5 正式推出
- 如果要開發網頁程式,那種程式語言最適合?
- ZK好用嗎?台灣有什麼網站使用這個框架?
- 時值四川震災, 駭客卻發動大規模攻擊
- 想要學習單元測試的話,有什麼比較好的入門書或網路資源嗎?
- 如何在Apache中區隔出不同程式可以使用的系統資源量
- 分類檢索 classified retrieval
- ASP網頁還能存活幾年?
- 8/11,Flex 3.0 教學 / 突破Web 2.0擴展AIR (第三班)
- RIA四雄群起:以Google Trends評析現有RIA四大技術(Flex、Silverlight、JavaFX、Cu
- 什麼是網頁掛馬?
- 使用Ajax的網頁安全性







