編者按】國家戰略層面的重視與投入,云計算與大數據等技術的深入,“互聯網+”驅動下私有云、混合云和公有云的發展,使得安全——軟件安全、云計算安全、移動安全、物聯網安全、大數據安全等,正在從某一技術領域應用演變為多企業間的全面行動。這也是2015年千人安全大會在北京頻辦的根本原因。高速發展的背后,是網絡安全邊界正在被無限拓寬且變得日益復雜的現狀。我們可以看到,傳統的固定邊界在新信息攻防形式下 逐漸無效,Design for Failure、攻擊面控制、縱深防御、實時安全情報感知等新安全體系建設開始嶄露頭角,更多企業的安全實踐已經“從0到1”。為此,我們策劃了程序員電子刊的《安全•實踐》(15日出刊)封面選題,其中有安全產業的觀察,安全人才流動性的分析,架構師設計中的常見安全誤區的解讀,大型私有云安全體系的剖析,也有多家典型互聯網公司安全實踐的經驗總結,更有手機安全 、攻擊平臺等熱點技術的追蹤。本篇為其中一篇。安全的世界這么大,呈現出來的只是其中很小一部分,更多的價值實踐,有待我們的共同分享。
自然世界中,先天有缺陷的生物總是容易被細菌病毒入侵,而健壯的生物更能抵抗細菌病毒的攻擊,計算機系統也是一樣,若有先天的架構設計安全缺陷,那么在面臨網絡攻擊的時候,就更容易被入侵或者破壞,甚至因為設計架構的原因,有些漏洞完全沒有辦法修復!本文將講述架構設計中需要避免出現的安全誤區,以幫助我們研發人員設計出更安全健壯的軟件架構。本文的舉例既有硬件架構,也有軟件架構,還有基礎架構等等不同的架構,但其中原理適用于所有的架構設計。下文將從兼容性設計誤區,降低成本設計誤區,數據和代碼不分離的設計誤區,封閉設計的誤區,黑名單設計的誤區,沒有將安全列為設計目標之一的誤區,總共6個方面來探討設計安全誤區的問題。
兼容性設計的誤區
兼容性越好的架構越能適應未來變化的需要,所以架構設計者會非常關注架構的兼容性設計,但是有些兼容性設計會帶來嚴重的安全漏洞,這些安全漏洞甚至無法以簡單的漏洞補丁方式修復。
以蘋果的USB-C接口設計為案例。USB-C這個接口不僅用來實現供電、還用于支持鼠標,鍵盤等設備的數據傳輸,起到了簡化設計結構,方便用戶的目的。谷歌新款Chromebook Pixel也內置了USB-C接口,預示著業界對于MacBook的USB-C接口設計基本上是一致認可的。不過,安全專家卻認為這是一個很糟糕的設計。在2014年的黑帽技術大會上,安全專家演示了一次針對USB-C接口的攻擊,只要將特制的U盤插入使用USB-C接口的蘋果計算機,攻擊者無需在做任何操作,就可以將后門或是病毒自動植入蘋果計算機,使計算機可以被攻擊者遠程控制或是通過病毒自動破壞計算機內的文件,非??膳拢「瘎〉倪€在后面,蘋果一直都沒有辦法修復該漏洞,為什么呢?這得從這個漏洞的利用方式說起,上文說到攻擊需要特制的U盤,安全專家改變了U盤的硬件和軟件結構和內容,當U盤插入USB-C接口的蘋果計算機時,電腦會識別U盤為一個鍵盤,再利用U盤中的芯片和存儲的攻擊代碼,就可以偽裝成鍵盤向主機發送控制命令,從而完全控制主機,無論使用者是否開啟自動播放,都可以成功。所以漏洞的關鍵在于U盤和鍵盤等設備可以共用同一類接口與計算機交互,在計算機系統上沒有辦法區分偽裝成鍵盤的U盤和真實的鍵盤,這樣若不改變USB-C接口可以兼容U盤,鍵盤等各種硬件的設計,他們就不能修復該漏洞,而若要修復該漏洞就必須推翻原來的設計,讓USB接口不再兼容鍵盤,鼠標等輸入硬件,輸入類硬件仍然使用原來的PS/2接口或其它不同的接口。
蘋果的USB-C接口設計產生了一個必須推翻自己才能修復的漏洞, 所以說這是一個糟糕的設計。對于軟硬件的兼容性設計,第一,一定要注意兼容的對象是否為同一類,不同類的對象最好不要強容,蘋果這個設計就沒有將控制指令的輸入設備(鍵盤)與數據輸入設備(U盤)這兩類對象區分對待,導致了這個越權漏洞的產生;第二,兼容性設計者需要確保鑒權機制能夠識別不同的對象輸入,對不同的對象輸入走不同的處理,避免出現控制指令輸入設備可以偽裝數據輸入設備,代碼可以偽裝成數據輸入的漏洞,借用一句經典的話——“圈子不同,不要強容”。
降低成本設計的誤區
架構設計者也會非常關注架構的成本,能以最少的成本實現系統是體現設計者水平的重要標志,所以架構設計者的設計總有降低軟硬件成本的傾向,這種傾向本沒有錯,但如果在錯誤的地方降了成本,給系統帶來極大的安全風險,就得不償失了。
例如下面這個因為降成本設計導致服務器無法防范CC攻擊的場景。很多設計者會將每臺服務器的負載率設定得非常高,高達50%-70%,希望減少服務器的部署以降低成本,但是在正常業務場景下就有這么高的負載,被CC攻擊的時候會很容易被癱瘓,安全專家也沒有辦法在服務器上實施安全策略以防御攻擊。CC(Challenge Collapsar)是一種http層的DDOS攻擊,它通過發送大量http層的請求,以達到讓被攻擊的目標網站癱瘓的目的。Challenge Collapsar的中文意思是挑戰黑洞,大家可能會覺得它的名字有點怪,這里涉及攻擊命名者與一個防火墻產品的糾葛,黑洞是一款知名的防火墻產品,意思很明顯了,命名者想說黑洞防火墻也防不住他的這種攻擊。目前國內領先的幾家DDOS清洗設備安全廠商可以基于特征防御一些普通的CC攻擊,但是對于一些沒有數據段特征,并且有大量代理ip的CC攻擊仍然沒有辦法。這個時候防御的重點戰場就必須轉移到服務器上來了,通過業務服務器上更多業務場景的數據,以及更容易編程實現復雜的安全策略優勢來檢測攻擊請求,舉個例子,比如我們通常業務場景下,來自河南省的訪問量很少,而攻擊的時候該省的訪問量上升10倍,我們可以對該省的訪問量丟掉80%,從而防御攻擊,并且最大限度的降低對業務的影響。
所以設計時保證一定的服務器冗余,能夠降低攻擊開始階段系統就被攻擊到癱瘓的概率,也為DDOS安全專家的安全防御策略提供計算資源。如果有條件的話,最好是把業務部署在云上,這樣被攻擊的時候可以動態增加服務器數量,既能節省成本也能保障攻擊的時候能夠有效的防護。
數據和代碼不分離的設計誤區
數據和代碼不分離意味著數據可以被當成代碼執行,而數據是可以由用戶(攻擊者)自己定義的,也就是說用戶(攻擊者)可以自定義在系統上執行的代碼,那么攻擊者可以構造木馬代碼,作為數據輸入給系統,系統執行這些木馬代碼后,系統就會被攻擊者控制,這樣的設計將給系統帶來極大的風險。我們的系統開發過程中其實有不少這樣的案例,下面我們先看看一個設計導致的上傳攻擊漏洞的案例。
例如一個導致上傳攻擊漏洞的設計案例,先簡單描述一下上傳攻擊的原理,大部分應用系統都有上傳圖片或文件的功能,攻擊者利用這些功能上傳一個網頁木馬,如果存放上傳文件的目錄有執行腳本的權限,那么攻擊者就可以直接得到一個WebShell,進而控制web服務器。這個漏洞有兩個必要條件,一是可以上傳木馬,二是存放上傳文件的目錄具備執行腳本的權限。上傳是業務的功能需要,即便有做各種安全過濾,限制木馬上傳,但也有各種繞過過濾的攻擊方法,比較難以限制。所以漏洞的關鍵就在上傳的目錄是否具備執行腳本的權限上,很多設計者會基于降低成本的考慮,將存儲上傳文件的位置與web應用程序放在同一服務器,甚至同一目錄下,這樣上傳的目錄也和web應用程序一樣具備執行腳本的權限,從而導致系統產生了一個高危上傳漏洞。
而如果將存儲上傳文件的位置設計在另一臺只具備存儲功能的文件服務器或數據庫上,與web應用服務器分開,這樣即使木馬被上傳進來,也因為文件服務器不能執行腳本而沒有辦法實施攻擊。
封閉設計的誤區
架構師設計通常會遵循對擴展開放,對修改封閉的設計原則。對于修改封閉,就是說外部可以調用系統的接口使用系統的功能,但是看不到系統內部實現的代碼,也不能對內部實現的代碼進行修改。這常常給設計者一種錯覺,認為外部使用者不知道系統內部是怎么實現的,不知道存在的安全缺陷,從而放心大膽的在內部留下許多安全隱患,最常見的就是使用私有加密算法。
設計者常會直觀的認為私有算法擁有算法的秘密性,所以安全性要比公開常用加密算法更高些。但其實私有算法的秘密性也是很難保障的首先,中國有句古語——“天下沒有不透風的墻”,指不定什么時候你的算法就會通過隊友泄露出去,如果你覺得這個說法太虛了,舉個實際的例子,開發人員都喜歡用github,指不定哪個豬隊友(有可能是自己)就會把你的算法全部上傳到github,黑客會放過這么好的機會嗎?當然不會,烏云上這些漏洞案例比比皆是。其次,如果算法沒有泄露,黑客就不知道你的算法了嗎?當然不是,黑客可以通過很多數學推導的方式,把加密的算法推導出來,例如加密算法的公式通常如下所示:
y= F(x) 其中F是加密算法,y是密文,x是明文
但只要有足夠多的 x,y 就可以推導出 F,比如下面一組【x,y】的數據:
x=[0 0.9375 1.8750 2.8125 3.7500 4.6875 5.6250 6.5625 7.5000
8.4375 9.3750 10.3125 11.2500 12.1875 13.1250 14.0625 15.0000];
y=[0.000000E+000 8.789063E-003 3.515625E-002 7.910156E-002
1.406250E-001 2.197266E-001 3.164063E-001 4.306641E-001
5.625000E-0017.119141E-001 8.789063E-001 1.063477E+000
1.265625E+000 1.485352E+000 1.722656E+000 1.977539E+000 2.250000E+000];
通過matlab的最小二乘法就可以計算出F的公式如下:
加密算法是這樣,其它的設計也是這樣,黑客總是可以通過各種方法收集到攻擊目標的大量信息,要知道攻擊的第一步就是情報收集。所以,使用私有加密算法并不能保證加密算法的私密性,對安全性提升也微乎其微。再加上私有算法的數學復雜性難以達到和公開常用算法的一樣水平(比如RSA算法利用的就是“將兩個大素數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難”的數學原理), 在算法的實現上也不如公開常用算法一樣久經考驗,因此即便封裝了的私有加密算法也是不能使用的,加密應該用公開常用的加密算法,用密鑰秘密性而不是算法的秘密性來保障安全。
所以,通過此類通過封閉設計隱藏軟件的實現,從而隱藏一些安全隱患是非常不可取的!官方機構對此類行為也有過明確的意見,反對采用執行或者實現的秘密性來保障產品的安全,美國國家標準與技術研究所(NIST)明文表示:“系統的安全性不應該依賴于執行或其部件的秘密性。軟件的設計應該假設是開放的——用戶和黑客都知道軟件是怎么樣實現的,而且即便知道軟件的實現也不會危害產品的安全,通過密鑰或者鑒權因子就能保障產品數據的安全。
黑名單防御的誤區
通常設計者都會知道需要防御sql注入和XSS攻擊等安全問題,但是在選擇防御的方案時常常走入一些誤區, 他們通常會選擇用過濾的方法去防御sql注入和XSS攻擊等攻擊,這種類似黑名單的防御方式簡單方便,修改量小,而且他們認為這樣黑客已經攻不進來了。他們低估了黑客們的智慧和毅力,事實證明凡是采用過濾方式防御sql注入和xss的產品,無一不被繞成狗的。
烏云上這種被繞過的案例比比皆是,目前還沒有看到有一個不被繞過的硬件防火墻,云WAF或主機端的防護產品,即便最新宣稱“永別了SQL注入”的SQLChop也很快在烏云被爆出存在繞過的漏洞, 筆者也贊同SQLChop的用數據分析檢測SQL注入的思路把防護水平提高了一個等級,但即便這樣也依然逃脫不了被繞過的命運。這些如此專業的安全廠商設計的產品都難逃被繞過的命運,那我們自己的研發人員自己在服務器上開發和部署的SQL注入和XSS攻擊過濾功能,是不是會被繞得更慘呢?答案是肯定的。所以對SQL注入漏洞應該用參數化查詢的方式來解決,XSS漏洞應該用對輸出進行編碼的方式來解決,過濾的方法只能作為臨時方案用來輔助做深度防御,而絕不能單獨作為防御攻擊的安全解決方案。
沒有將安全列為設計目標之一的誤區
相比以上誤區,大部分設計最大的誤區就是沒有將安全列為設計的目標之一,這才是產生以上所有設計安全問題的根源。產生這樣誤區的主要原因有兩個,第一,架構師或設計者真心不覺得有人有能力和有耐心去攻擊他們的產品。我在與架構師的溝通中,聽到最多的一句話就是“不可能!”,不管是最優秀互聯網企業的架構師,還是最優秀傳統企業的架構師都是這樣。架構師或設計者們通常以自己的知識去判斷是否能被攻擊,但是大部分的架構師和設計者都不具備一定深度的安全知識,所以常常作出錯誤的判斷。黑客是最具極客精神的群體,為挖掘一個漏洞連續調試12小時,持續攻堅一個星期都不是什么稀奇的事情,所以在這樣一個群體面前,絕不能以己度人,聽從靠譜安全架構師的意見會更安全。第二,存在安全漏洞并不一定立即發生安全事故。昆山做小程序公司安全問題大多數情況下都只是風險,它轉化為安全事故一般有一段時間,而且很多情況下即便發生了安全事故,一些安全力量薄弱的公司甚至不能檢測和感知到,所以表面的一片“和諧”給了我們的設計者一種錯覺,不需要做安全的設計,產品給我的需求都做不完,哪有時間”浪費”人力的做安全設計和開發!