建立安全的Web應用程式
前言:本篇文章主要談談安全的一些概念的問題,基本但決不是沒有用。大家看看有平時我們所理解的安全的概念有什麼不同。
系列文章連結:
ASP.NET開發安全問題
ASP.NET安全問題-- 建立安全的Web應用程式
ASP.NET安全問題--ASP.NET安全架構
ASP.NET安全問題--ASP.NET安全架構--如何?.NET安全
ASP.NET安全問題--ASP.NET生命週期中的驗證以及身分識別驗證模組
ASP.NET安全問題--Forms驗證的具體介紹(上篇)
ASP.NET安全問題--Froms驗證的具體介紹(中篇)
ASP.NET安全問題--Forms驗證(後篇)--實戰篇
ASP.NET安全問題--ASP.NET中的授權問題(前篇)
把一個問題說清楚,是要有前提的,也要大家有一些通過的詞彙,就像大家談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是基於Managed 程式碼的,也就是說.net的代碼不是直接操作記憶體,而是在中間隔了一層CLR。Managed 程式碼的執行要靠CLR來為止作為邊界檢查,所以CLR中的任何脆弱性都將轉變為應用程式的脆弱性。如果有高手知道了CLR的問題,那麼,Managed 程式碼也出問題。
指令碼注入和跨站指令碼攻擊
任何時候我們都要有這個心理:使用者都是惡意的。所以我們不能信任使用者的任何輸入,在使用者輸入的時候一定要檢驗。假如沒有正確的處理好使用者的輸入,就可能在程式中引入指令碼注入的脆弱性。該脆弱性允許使用者將自己額指令碼注入到資料中,如在使用者留言中,使用者插入"<script>alert('Error')</script>",那麼我們的留言的頁面就中是彈出提示。
跨站指令碼的攻擊一般表現為一個在URL參數中帶有用戶端的指令碼。這些指令碼用來盜取使用者的cookie資訊等,
我們這裡只是簡單的說下,後面的一些文章還會具體的談,以及解決方案。
SQL注入
相信這個問題,大家或多或少都知道一些,主要是惡意的使用者在我們的程式的資料庫中執行精心設計的SQL語句。而且威脅很大,設定可以擷取伺服器的管理員的許可權。
分散式阻斷服務
也稱為DDOS(Disrtibute Denial Of Service)。DDOS攻擊主要就是用大量的電腦攻擊一個系統。很多的電腦聯合起來就可以發送很多的虛假的請求,以至於被攻擊的系統超負荷,而不能向其他的使用者提供服務。
蓄意工具者為了發動DDOS,就必須擷取足夠多的機器。惡意的使用者設計在別人的電腦上注入木馬和病毒,擷取機器的控制權,"借"別人的電腦發送攻擊。被控制的電腦就是所謂的"殭屍"。
DDOS攻擊一般來攻擊伺服器,而且攻擊的方式也是防不勝防,很多的防護軟體和防火牆不能區分正確的請求和虛假的請求。
人的問題
有時候,被利用的脆弱性不是技術上的脆弱性,而是人的脆弱性。如果使用者沒有安全的意識,就容易受騙,而為攻擊者開啟系統的。方式很多,如用Email欺騙使用者,誘使使用者執行一些程式,還有就是蠕蟲...
蠻力攻擊
如果不採取一定的措施防止使用者無休止的嘗試串連應用程式,那麼我們就容易受到不計其數的猜測密碼口令的攻擊,即蠻力攻擊。
攻擊的方式主要就是設計一個程式,用它向目標應用發送很多的請求以測試不同的密碼口令。
有一點要注意:考慮安全問題的時候,我們常常把程式比作為一個城堡,在城堡的周圍建造城牆並且嚴格盤查各個通道。保護Web程式與此類似,但是,如果這樣,那麼我們對於已經進入城堡的使用者就無計可施了。
三 安全由誰來負責
很多時候安全問題不僅僅只是程式員的責任,而是在系統設計的時候就開始考慮的問題,而且系統的安全也是由很多的人來負責的,如:
程式設計者要保證程式結構是安全的
網路系統管理員要保證網路和伺服器是安全的
程式員要保證代碼不會引入脆弱性
資料庫管理員確保資料庫伺服器沒有脆弱性
使用者也不要受欺騙
當然,還有其他的很多任務要做好,才能實現安全。
我們都是開發人員,下面就來看看我們開發人員不能解決的問題:
網路
ASP.NET程式運行要依附於網路,如果網路連接中斷,我們沒有辦法。
Web伺服器和資料庫伺服器
如果伺服器本身不安全,那麼我們的代碼寫的再好也徒勞。
用戶端
我們終究能控制用戶端,而且很多的惡意使用者甚至可以繞過我們的用戶端的javascript驗證,要記住使用者都是惡意的.
我們可以解決的問題:
把安全放在第一位
構建並維護具有一定安全等級的系統,是重要而又困難的事情。以前,安全問題往往被認為是外部的問題,在程式種不考慮。
客戶和管理者永遠也不會同意為了某個功能而花費金錢,除非他麼能夠看到明顯的好處。作為程式員,我們有責任教育公司其他的人,使得他們明白安全的重要性,不能像以前那麼只是把安全的問題輕描淡寫,而是要作為核心的功能引入系統。安全功能永遠是系統核心功能。
實現穩固的安全功能
為了達到系統安全的目的,作為ASP.NET開發人員,我們要在程式種增加功能。安全的系統都是經過嚴格的測試和審查的。我們後面的問題會詳細的講述ASP.NET的安全架構。
避免增加新的脆弱性
在向程式種增代碼時,可能引入新的脆弱性。對於新增加的代碼,要嚴格的審查,確保不會造成安全性漏洞。
我們很多時候都是先把功能實現,然後再來考慮安全的問題,做一些維護。這樣做很危險,所以我們在項目開始時候就考慮安全的問題。
還有就是要記得刪除我們程式中的明顯的漏洞。我們可能在開發調試的時候用了測試代碼,如:
public bool ValidateUser(string userName)
{
//testCode
if(userName="app")
return true;
//....
}
我們可以在代碼中加//testCode(見上),然後項目完成後尋找所有的"testCode",將其刪除。
還有就是我們也教育使用者,是他們對安全問題有一定的瞭解;我們對於使用者的輸入都要驗證,還是那句話:所有使用者都是惡意的。
四 給出一些建議
沒有百分百的安全
電腦安全領域中有個說法,"唯一安全的系統是鎖在安全櫃中而沒有通電的系統"。我們必須承認,系統不可能決定安全,如果攻擊者有足夠的能力和耐心,他們終會找到侵入系統的方法。
既然不可能絕對的安全,我們怎麼辦?我們可以儘可能的給未經授權的訪問系統加大難度。這樣就好比增加了護欄的高度,攻擊者想要擷取存取權限,就得付出更多的努力。而且很多的攻擊者都是有投機的心理的-只找容易攻擊的對象。
藏起來不能保證安全
我們常常將一些私人的檔案藏在Web網站的秘密目錄中,然後只告訴我們信任的人。可是,隱藏不能保證真正的安全。例子很多,如,公司在Web頁面上使用隱藏的串連提供對"私人"目錄的訪問。這些串連可能是用一種透明圖形隱藏在某個角落,對於Web頁面的人不可見,但是對於網路搜尋引擎來說,那麼隱藏的連結和別的連結毫無分別。
所以,隱藏不一定安全。而且現在的常常用密碼編譯演算法,之所以用是因為演算法經過了嚴格的審查和破解測試,在一定時間內演算法是安全的,假如有個演算法,破解需要幾十年甚至更長時間,在現有階段,我們使用也可說是安全的。
應用程式的安全性由它最薄弱的環節決定
大家都知道水桶的模板原理:水桶裝水的多少,由最短的那塊模板決定的。安全問題也一樣的。因為惡意的使用者想進入系統,會嘗試很多的方式很途徑,一旦程式的最薄弱的環節被找到,整個系統可想而知。
建議在系統開發和完成的時候,構建出系統的結構圖,然後標註從客戶機一直到終端的資料庫伺服器所有環節,然後分析之間的串連情況,思考可能出問題的地方,改進。
安全問題貫穿項目開發
從項目的設計直到後期的部署,安全都要考慮。不要到最後才添加安全措施。
過分安全將會不利於項目的開發
有些時候,過度的強調安全不是好事情。如果系統安全很苛刻,如系統要求使用者的密碼必須是12位字元,而且還要有2個非數字字元,還要有大寫,小寫字母。使用者很可能就記不住密碼,甚至他們把密碼直接寫在紙上貼在電腦上,那麼什麼安全都沒有了。所以安全的方案要折衷,和使用者多商量。
安全不僅僅只是技術的問題
前面也講過,在安全方面我們開發人員可以做的事情,很多的時候,使用者是安全薄弱的環節,所以還要加強使用者安全教育。
好了,今天羅羅嗦嗦的說了不少,希望大家體諒,只是開篇,概念不少,很多的東西到後面講,才能水到渠成。
感謝各位!
註:轉載要表明出處!