吳 全,錢小軍,金 龍
(江蘇金盾檢測技術有限公司,江蘇 南京 210013)
目前,國內(nèi)的軟件服務外包行業(yè)發(fā)展迅速,對人才的需求量也急劇攀升,使軟件服務外包人才供不應求,而當前高校的教學內(nèi)容又與企業(yè)的用人需求存在明顯的差距,高校畢業(yè)生無法立即投入工作。國內(nèi)有很多的培訓機構,他們各有著自己的一套培訓流程和教學方案,水平參差不齊。近年來雖然很多高校為了加強學生的實踐編程能力,與這些培訓機構合作在教學大綱中加入了實踐課程,但是靠著短短幾周的突擊填鴨式教學,所完成的項目多半是不嚴謹?shù)?,存在著諸多安全問題。不僅是培訓機構會忽視開發(fā)中的安全問題,很多軟件公司的從業(yè)人員也很少考慮過項目的安全性。尤其是在開發(fā)小型系統(tǒng)或者針對內(nèi)網(wǎng)的系統(tǒng)時,為了方便調(diào)試和使用,開發(fā)方和運維方都會忽視應用的安全問題。下面我們以Web系統(tǒng)為例,簡略地探討在外包項目中開發(fā)人員很少會關注到卻又十分重要的安全問題。
在很多需要權限分級管理的系統(tǒng)中,開發(fā)人員在登錄、注冊等頁面里處理用戶的密碼時,通常的做法只是將用來填寫密碼的文本框的type屬性設置為password,使得密碼字段中的字符通過特殊符號進行替換以達到隱藏的作用[1]。但在用戶提交信息到服務器時,卻讓密碼以明文的方式進行傳輸??雌饋硎且粋€很小的問題,但是,在實際應用中,這是個很大的隱患。很多開發(fā)人員可能也考慮過這個問題,只是鑒于應用用戶較少,而且只能處于內(nèi)網(wǎng)環(huán)境中,就直接忽略了[2]。但是表單中明文傳送密碼,一旦流量被惡意攻擊者嗅探到,就可能產(chǎn)生一定的不良影響。最簡單的解決方式是將密碼通過js加密后再傳遞到后臺,然后控制器在校驗密碼時直接取數(shù)據(jù)庫中的密文進行匹配[3]。
這個問題可能出現(xiàn)在密碼校驗邏輯中:校驗結(jié)果的不同分支,返回給頁面提示信息不同,密碼錯誤和用戶名不存在是兩個不同分支中的。這樣一來,居心叵測者就可能通過多次輸入并提交而猜中系統(tǒng)中可能存在的用戶名。同時,攻擊者還可以暴力枚舉來嘗試獲得用戶的密碼,如果用戶的密碼強度較為脆弱,很容易被攻擊者枚舉出密碼[4]。因此,對于用戶的操作需要作出跟蹤限制,對于可能是非法操作的用戶,暫停對其的服務;或者在提交數(shù)據(jù)時加上驗證碼等防止自動化攻擊的方式,這樣加大攻擊者的攻擊成本來進行防御,同時對用戶的使用影響可以降到最低。
“永遠不要相信用戶的輸入”是對設計人員和編碼人員說的,是進行安全設計和安全編碼的重要準則。換一句話來說,就是用戶在任何時候所輸入的數(shù)據(jù)在證明其無害之前,都是有害的。許多危險的漏洞就是因為過于相信用戶的輸入是善意的而導致的。而很多不成熟、速成的開發(fā)者,只關注功能上的實現(xiàn),很容易忽視對用戶的輸入的檢查。有些開發(fā)者在前端頁面上使用js對用戶的輸入進行限制,將數(shù)據(jù)通過POST方法提交后便覺得高枕無憂,在后端便放松了對用戶輸入數(shù)據(jù)的檢查,認為傳遞來的參數(shù)一定是符合設計規(guī)則的。然而,攻擊者可以使用burpsuite和fiddler等代理工具,對數(shù)據(jù)包中的數(shù)據(jù)進行修改。這時候,如果后端的程序沒有對用戶輸入數(shù)據(jù)進行檢查,這樣的惡意數(shù)據(jù)如果傳遞到拼接的sql語句中,就可能會造成sql注入漏洞;如果被顯示在頁面上,可能造成跨站腳本攻擊漏洞等。項目的開發(fā)一般是由團隊完成的,稍微復雜一些的項目,更會有數(shù)不清的用戶輸入點,一旦其中的一個輸入點沒有對用戶輸入進行檢查,便有可能對整個系統(tǒng)的產(chǎn)生威脅。
有些開發(fā)人員會說對輸入數(shù)據(jù)進行如此多的檢查會影響性能,實際上,大多數(shù)輸入檢查并不對性能造成大的損害,即使有損害,一個稍慢但是相對安全的系統(tǒng)也比一個快速但容易受到攻擊的系統(tǒng)要好。如果客戶對你的系統(tǒng)性能不滿意,應尋找其他途徑提高性能,不要通過減少安全檢查來提高性能,因為當客戶的系統(tǒng)因漏洞被攻破以后,你面臨的就不是幾句抱怨,而是一場災難了。正確的做法是在客戶端和服務端都作相同的檢查,客戶端的檢查的目的是為了界面的友好、節(jié)省用戶的時間,服務端的檢查才是為了數(shù)據(jù)的完整和安全。
一些Web應用的404、500頁面使用的是容器默認的頁面,而有些默認報錯頁面不僅對用戶不友好,還會造成服務器敏感信息的泄露[5]。增強安全意識,應該避免使用服務器默認的錯誤頁面信息。
很多網(wǎng)站管理維護人員,為了維護網(wǎng)站時的便利,會在服務器上留下有規(guī)律的備份文件。這些文件如果被攻擊者枚舉猜測到,便會造成不同程度的安全威脅[6]。
近年來隨著版本控制系統(tǒng)的流行,很多團隊在結(jié)束開發(fā)時會忘記刪除版本控制系統(tǒng)的目錄,比如.git,.svn目錄,這種項目部署后可能會造成網(wǎng)站應用代碼泄露的風險。此外,開發(fā)人員在使用版本控制系統(tǒng)時可能會將代碼同步到公開的平臺上,在這一過程中會將開發(fā)或者生產(chǎn)環(huán)境中的配置文件里可能存在的敏感信息刪除,便會導致攻擊者通過公開在平臺里的項目獲取到敏感信息[7]。
目錄遍歷漏洞指通過在URL或參數(shù)中構造 ../,./ 和類似的跨父目錄字符串的ASCII 編碼、unicode 編碼等,完成目錄跳轉(zhuǎn),讀取操作系統(tǒng)各個目錄下的敏感文件,也可以稱作“任意文件讀取漏洞”[8]。
目錄遍歷漏洞原理從根本上來說還是因為開發(fā)人員在編寫程序時沒有充分檢查用戶的輸入,沒有過濾用戶輸入的../ 之類的目錄跳轉(zhuǎn)符,導致用戶可以通過提交目錄跳轉(zhuǎn)來遍歷服務器上的任意文件。使用多個.. 符號,不斷向上跳轉(zhuǎn),最終停留在根 /,通過絕對路徑去讀取任意文件。因此,更應當針對不同功能時刻注意檢查用戶的輸入。
此外,對于nginx等HTTP和反向代理服務器的配置失誤,也可能造成目錄遍歷漏洞。
例如,在nginx的網(wǎng)站配置中,使用如下的配置:
location /xxxx {
alias /var/www/html/xxxx/;
}
location /admin {
alias /var/www/html/admin/;
}
location沒限制后面,那/admin./就會被好心的nginx處理成/admin/./,同理/admin../就會被nginx處理成/admin/../,便可能將網(wǎng)站根目錄里的信息通過nginx的Directory list列出來。
CSRF(Cross-Site Request Forgery),中文名稱即為“跨站請求偽造攻擊”。攻擊者可以盜用用戶的登錄信息,以用戶的身份模擬發(fā)送各種請求[9]。攻擊者只要借助少許的社會工程學的詭計,例如通過QQ等聊天軟件發(fā)送的鏈接(有些還偽裝成短域名,用戶無法分辨),攻擊者就能迫使Web應用的用戶去執(zhí)行攻擊者預設的操作。例如,當用戶登錄網(wǎng)絡銀行去查看其存款余額,在他沒有退出時,就點擊了一個QQ好友發(fā)來的鏈接,那么該用戶銀行賬戶中的資金就有可能被轉(zhuǎn)移到攻擊者指定的賬戶中。所以遇到CSRF攻擊時,將對終端用戶的數(shù)據(jù)和操作指令構成嚴重的威脅。當受攻擊的終端用戶具有管理員賬戶的時候,CSRF攻擊將危及整個Web應用程序。
CSRF的防御可以從服務端和客戶端兩方面著手,從服務端著手的防御效果比較好的,現(xiàn)在一般的CSRF防御也都在服務端進行。服務端的預防CSRF攻擊的方式方法有多種,但思路上都是差不多的,主要從兩方面入手,一方面是正確使用GET,POST請求和cookie,另一方面是在非GET請求中增加token。
一般而言,普通的Web應用都是以GET和POST請求為主,還有一種請求是cookie方式。在常規(guī)的開發(fā)模式中,GET請求常用在查看、列舉、展示等不需要改變資源屬性的時候;POST請求常用在表單提交,改變一個資源的屬性或者做其他一些事情的時候。
當正確地使用了GET和POST請求之后,剩下的就是在非GET方式的請求中增加隨機數(shù),主要通過3種方式來進行:(1)要為每個用戶生成一個唯一的cookie token,所有表單都包含同一個偽隨機值,這種方案最簡單,因為理論上攻擊者不能獲得第三方的cookie。(2)讓每個POST請求使用驗證碼,這個方案算是比較完美的,但是需要用戶多次輸入驗證碼,用戶體驗比較差,所以不適合在業(yè)務中大量運用。(3)在渲染表單的時候,為每一個表單包含一個csrf Token,提交表單的時候,帶上csrf Token,然后在后端做csrf Token驗證[10]。
隨著B/S架構的Web應用飛速發(fā)展,其帶來的安全威脅也與日俱增,深深地影響到人們的生活。作為計算機軟件系統(tǒng)的開發(fā)、維護人員,更應當注意到網(wǎng)絡安全的重要性。本文通過對一些容易被忽視的安全問題進行了深入全面的分析,希望能為一些安全意識淡薄的開發(fā)編碼人員帶來一些安全開發(fā)上應考慮的問題和建議。