把一個問題說清楚,是要有前提的,也要大家有一些通過的詞匯,就像大家談OO,就知道談的面向對象,以及面向對象的一些特征;懂設計模式的,一聽到"觀察者",就立馬知道什麼意思。
一.下面看看安全的一些概念:
首先,我們來看看什麼是安全性?
我們常常提起“實現安全性”“創建安全的系統”。所以安全性一般是定義很多,如:安全性就是保證系統可以完全按照我們想要的方式運行;安全性就是防止以我們不希望的方式運行系統...定義很多,但是不知道大家有沒有發現,我們理解的安全的定義很狹窄的。怎麼說?我們一般認為安全就是這樣的:采取一定的措施(主要是編程代碼的措施)處理程序運行時的意外,或者防止意外發生。但是安全的問題不僅僅只是代碼的問題,所以在安全編程方面,我們要考慮的更多。
什麼是安全
我們不能保證一個系統絕對的安全,不可能做到100%的安全。安全的定義的受到很多的限制,首先我們來看看一個例子。
我們都用過銀行的ATM機,如果有人撿到了我們的卡想要盜取我們的錢,那麼他只有猜我們的密碼。如果密碼的長度只有一位數,那麼撿卡人第一次猜對的概率就是1/10,他只要十次就可以盜取我們的錢(假設可以不限次數的猜),那麼系統的安全行很差;如果密碼是2位,那麼密碼就有100中可能,那麼撿卡人第一次才對的幾率就是1/100,第二次就是1/99,第三次1/98...系統的安全行也很差.
如果把密碼的嘗試限制在3次,如果密碼為2位數,那麼密碼被猜出的幾率就大大的減小了:
第一次猜中的幾率就是1/100
第二次猜中(第一次沒有中)的幾率就是(99/100) * (1/99)=0.01
第三次猜中(前兩次不中)的幾率就是(99/100)*(98/99)*(1/98)=0.01
三次之內猜中的幾率就是:0.01+1.01+0.01=0.03
所以,當我們限制了嘗試的次數的時候,系統就比之前安全了一些,但是系統還並不是很安全,只能說比之前稍微的好了點,但是風險依然很大。
為了使得系統更加的安全,就要減小系統的密碼被猜出的可能行,我們可以從兩個方面著手:
1.使得密碼嘗試的次數減小,如用戶只能輸入一次密碼;
2.加大密碼的位數,如6位。這樣密碼被猜出的幾率就更加的小了,風險也小了很多,系統的安全行就又提高了。所以,我們常說安全不安全的,都只是一個相對的概念。說了這麼多,就是要說一點:不要把安全看死了,安全不安全要看我們的環境。
在談後面的話題之前,讓我們來共享一些術語:
脆弱性是系統的一個特征,它可能會使得應用系統不安全按照我們預想的方式運行。一般表示系統不好的特征。
威脅就是指利用錯人性破環系統安全的可能行。
利用就是利用脆弱行的方法。
總結一句話就是:脆弱行導致了威脅,利用則實現了威脅,簡言之,攻擊。
二、Web應用中的安全問題
首先我們就看看對Web的攻擊。攻擊有很多種的,其中一部分可以使用ASP.Net代碼進行防范的,但是其他的攻擊方式還是可以產生破壞的,如直接攻擊服務器。下面就來看典型的例子。
我們之前說過,攻擊就是利用系統的脆弱性以實現一定的威脅。攻擊的結果也很多,如:
未經授權的訪問--用戶獲取了更多的權限,從而可以將應用程序用於其他的途徑,如果獲取了網站的管理員的密碼,散布政治言論。
代碼執行--在目標系統上運行惡意代碼,而且還會導致其他的威脅,如木馬。
拒絕服務--合法用戶被禁止訪問應用程序
信息失竊--機密的信息被盜取
破壞信息--信息遭到修改。如,站點被塗改,發布攻擊性的消息和政治言論。
下面我們就來看看常見的一些脆弱性,以及對它們的利用,以及引起的威脅。
緩沖區溢出
這個問題由來已久,而且到現在為止,也是Web應用種最常被利用的脆弱性。
當應用程序的外部輸入沒有經過檢查就被插入內存的時候,就會存在緩沖區溢出的脆弱性。如果插入的長度超過了內存中為此分配的空間的長度,輸入就溢出,可能將占據內存中的其他的地方,甚至運行惡意的代碼。
對緩沖區溢出的主要利用就是把附加的數據寫到內存中緩沖區的其他地方,這樣就常常導致程序的崩潰,因為內存破壞了,這也是拒絕服務器的攻擊方式,如果附加的數據設計的很巧妙的話,附加的數據還可以重寫函數的返回地址,那麼程序就按照攻擊者的意願執行,病毒,木馬就是這樣。
當然,在c++中,這個問題很常見,因為C++可以直接操作內存地址,進行很底層的操作。但是在.Net中是否也有這個問題?
因為.net是基於托管代碼的,也就是說.Net的代碼不是直接操作內存,而是在中間隔了一層CLR。托管代碼的執行要靠CLR來為止作為邊界檢查,所以CLR中的任何脆弱性都將轉變為應用程序的脆弱性。如果有高手知道了CLR的問題,那麼,托管代碼也出問題。
腳本注入和跨站腳本攻擊
任何時候我們都要有這個心理:用戶都是惡意的。所以我們不能信任用戶的任何輸入,在用戶輸入的時候一定要檢驗。假如沒有正確的處理好用戶的輸入,就可能在程序中引入腳本注入的脆弱性。該脆弱性允許用戶將自己額腳本注入到數據中,如在用戶留言中,用戶插入" ",那麼我們的留言的頁面就中是彈出提示。
跨站腳本的攻擊一般表現為一個在URL參數中帶有客戶端的腳本。這些腳本用來盜取用戶的cookIE信息等,
我們這裡只是簡單的說下,後面的一些文章還會具體的談,以及解決方案。
SQL注入
相信這個問題,大家或多或少都知道一些,主要是惡意的用戶在我們的程序的數據庫中執行精心設計的SQL語句。而且威脅很大,設置可以獲取服務器的管理員的權限。
分布式拒絕服務
也稱為DDOS(Disrtibute Denial Of Service)。DDOS攻擊主要就是用大量的計算機攻擊一個系統。很多的計算機聯合起來就可以發送很多的虛假的請求,以至於被攻擊的系統超負荷,而不能向其他的用戶提供服務。
蓄意工具者為了發動DDOS,就必須獲取足夠多的機器。惡意的用戶設計在別人的電腦上注入木馬和病毒,獲取機器的控制權,"借"別人的電腦發送攻擊。被控制的電腦就是所謂的"僵屍"。
DDOS攻擊一般來攻擊服務器,而且攻擊的方式也是防不勝防,很多的防護軟件和防火牆不能區分正確的請求和虛假的請求。
人的問題
有時候,被利用的脆弱性不是技術上的脆弱性,而是人的脆弱性。如果用戶沒有安全的意識,就容易受騙,而為攻擊者打開系統的。方式很多,如用Email欺騙用戶,誘使用戶執行一些程序,還有就是蠕蟲...
蠻力攻擊
如果不采取一定的措施防止用戶無休止的嘗試連接應用程序,那麼我們就容易受到不計其數的猜測密碼口令的攻擊,即蠻力攻擊。
攻擊的方式主要就是設計一個程序,用它向目標應用發送很多的請求以測試不同的密碼口令。
有一點要注意:考慮安全問題的時候,我們常常把程序比作為一個城堡,在城堡的周圍建造城牆並且嚴格盤查各個通道。保護Web程序與此類似,但是,如果這樣,那麼我們對於已經進入城堡的用戶就無計可施了。
.三、安全由誰來負責
很多時候安全問題不僅僅只是程序員的責任,而是在系統設計的時候就開始考慮的問題,而且系統的安全也是由很多的人來負責的,如:
程序設計者要保證程序結構是安全的
網絡管理員要保證網絡和服務器是安全的
程序員要保證代碼不會引入脆弱性
數據庫管理員確保數據庫服務器沒有脆弱性
用戶也不要受欺騙
當然,還有其他的很多任務要做好,才能實現安全。
我們都是開發人員,下面就來看看我們開發人員不能解決的問題:
網絡
ASP.Net程序運行要依附於網絡,如果網絡連接中斷,我們沒有辦法。
Web服務器和數據庫服務器
如果服務器本身不安全,那麼我們的代碼寫的再好也徒勞。
客戶端
我們終究能控制客戶端,而且很多的惡意用戶甚至可以繞過我們的客戶端的Javascript驗證,要記住用戶都是惡意的.
我們可以解決的問題:
把安全放在第一位
構建並維護具有一定安全等級的系統,是重要而又困難的事情。以前,安全問題往往被認為是外部的問題,在程序種不考慮。
客戶和管理者永遠也不會同意為了某個功能而花費金錢,除非他麼能夠看到明顯的好處。作為程序員,我們有責任教育公司其他的人,使得他們明白安全的重要性,不能像以前那麼只是把安全的問題輕描淡寫,而是要作為核心的功能引入系統。安全功能永遠是系統核心功能。
實現穩固的安全功能
為了達到系統安全的目的,作為ASP.NET開發人員,我們要在程序種增加功能。安全的系統都是經過嚴格的測試和審查的。我們後面的問題會詳細的講述ASP.Net的安全架構。
避免增加新的脆弱性
在向程序種增代碼時,可能引入新的脆弱性。對於新增加的代碼,要嚴格的審查,確保不會造成安全漏洞。
我們很多時候都是先把功能實現,然後再來考慮安全的問題,做一些維護。這樣做很危險,所以我們在項目開始時候就考慮安全的問題。
還有就是要記得刪除我們程序中的明顯的漏洞。我們可能在開發調試的時候用了測試代碼,如:
以下為引用的內容:我們可以在代碼中加//testCode(見上),然後項目完成後查找所有的"testCode",將其刪除。
還有就是我們也教育用戶,是他們對安全問題有一定的了解;我們對於用戶的輸入都要驗證,還是那句話:所有用戶都是惡意的。
四、給出一些建議
沒有百分百的安全
計算機安全領域中有個說法,"唯一安全的系統是鎖在安全櫃中而沒有通電的系統"。我們必須承認,系統不可能決定安全,如果攻擊者有足夠的能力和耐心,他們終會找到侵入系統的方法。
既然不可能絕對的安全,我們怎麼辦?我們可以盡可能的給未經授權的訪問系統加大難度。這樣就好比增加了護欄的高度,攻擊者想要獲取訪問權限,就得付出更多的努力。而且很多的攻擊者都是有投機的心理的-只找容易攻擊的對象。
藏起來不能保證安全
我們常常將一些私人的文件藏在Web站點的秘密目錄中,然後只告訴我們信任的人。可是,隱藏不能保證真正的安全。例子很多,如,公司在Web頁面上使用隱藏的連接提供對"私人"目錄的訪問。這些連接可能是用一種透明圖形隱藏在某個角落,對於Web頁面的人不可見,但是對於網絡搜索引擎來說,那麼隱藏的鏈接和別的鏈接毫無分別。
所以,隱藏不一定安全。而且現在的常常用加密算法,之所以用是因為算法經過了嚴格的審查和破解測試,在一定時間內算法是安全的,假如有個算法,破解需要幾十年甚至更長時間,在現有階段,我們使用也可說是安全的。
應用程序的安全性由它最薄弱的環節決定
大家都知道水桶的模板原理:水桶裝水的多少,由最短的那塊模板決定的。安全問題也一樣的。因為惡意的用戶想進入系統,會嘗試很多的方式很途徑,一旦程序的最薄弱的環節被找到,整個系統可想而知。
建議在系統開發和完成的時候,構建出系統的結構圖,然後標注從客戶機一直到終端的數據庫服務器所有環節,然後分析之間的連接情況,思考可能出問題的地方,改進。
安全問題貫穿項目開發
從項目的設計直到後期的部署,安全都要考慮。不要到最後才添加安全措施。
過分安全將會不利於項目的開發
有些時候,過度的強調安全不是好事情。如果系統安全很苛刻,如系統要求用戶的密碼必須是12位字符,而且還要有2個非數字字符,還要有大寫,小寫字母。用戶很可能就記不住密碼,甚至他們把密碼直接寫在紙上貼在電腦上,那麼什麼安全都沒有了。所以安全的方案要折衷,和用戶多商量。
安全不僅僅只是技術的問題
前面也講過,在安全方面我們開發人員可以做的事情,很多的時候,用戶是安全薄弱的環節,所以還要加強用戶安全教育。