官术网_书友最值得收藏!

第一篇 世界觀安全

第1章 我的安全世界觀

互聯(lián)網(wǎng)本來是安全的,自從有了研究安全的人之后,互聯(lián)網(wǎng)就變得不安全了。

1.1 Web安全簡史

起初,研究計算機(jī)系統(tǒng)和網(wǎng)絡(luò)的人,被稱為“Hacker”,他們對計算機(jī)系統(tǒng)有著深入的理解,因此往往能夠發(fā)現(xiàn)其中的問題。“Hacker”在中國按照音譯,被稱為“黑客”。在計算機(jī)安全領(lǐng)域,黑客是一群破壞規(guī)則、不喜歡被拘束的人,因此總想著能夠找到系統(tǒng)的漏洞,以獲得一些規(guī)則之外的權(quán)力。

對于現(xiàn)代計算機(jī)系統(tǒng)來說,在用戶態(tài)的最高權(quán)限是root(administrator),也是黑客們最渴望能夠獲取的系統(tǒng)最高權(quán)限。“root”對黑客的吸引,就像大米對老鼠的吸引,美女對色狼的吸引。

不想拿到“root”的黑客,不是好黑客。漏洞利用代碼能夠幫助黑客們達(dá)成這一目標(biāo)。黑客們使用的漏洞利用代碼,被稱為“exploit”。在黑客的世界里,有的黑客,精通計算機(jī)技術(shù),能自己挖掘漏洞,并編寫exploit;而有的黑客,則只對攻擊本身感興趣,對計算機(jī)原理和各種編程技術(shù)的了解比較粗淺,因此只懂得編譯別人的代碼,自己并沒有動手能力,這種黑客被稱為“Script Kids”,即“腳本小子”。在現(xiàn)實世界里,真正造成破壞的,往往并非那些挖掘并研究漏洞的“黑客”們,而是這些腳本小子。而在今天已經(jīng)形成產(chǎn)業(yè)的計算機(jī)犯罪、網(wǎng)絡(luò)犯罪中,造成主要破壞的,也是這些“腳本小子”。

1.1.1 中國黑客簡史

中國黑客的發(fā)展分為幾個階段,到今天已經(jīng)形成了一條黑色產(chǎn)業(yè)鏈。

筆者把中國黑客的發(fā)展分為了:啟蒙時代、黃金時代、黑暗時代。

首先是啟蒙時代,這個時期大概處在20世紀(jì)90年代,此時中國的互聯(lián)網(wǎng)也剛剛處于起步階段,一些熱愛新興技術(shù)的青年受到國外黑客技術(shù)的影響,開始研究安全漏洞。啟蒙時代的黑客們大多是由于個人愛好而走上這條道路,好奇心與求知欲是驅(qū)使他們前進(jìn)的動力,沒有任何利益的瓜葛。這個時期的中國黑客們通過互聯(lián)網(wǎng),看到了世界,因此與西方發(fā)達(dá)國家同期誕生的黑客精神是一脈相傳的,他們崇尚分享、自由、免費的互聯(lián)網(wǎng)精神,并熱衷于分享自己的最新研究成果。

接下來是黃金時代,這個時期以中美黑客大戰(zhàn)為標(biāo)志。在這個歷史背景下,黑客這個特殊的群體一下子幾乎吸引了社會的所有眼球,而此時黑客圈子所宣揚(yáng)的黑客文化以及黑客技術(shù)的獨特魅力也吸引了無數(shù)的青少年走上這條道路。自此事件后,各種黑客組織如雨后春筍般冒出。此階段的中國黑客,其普遍的特點是年輕,有活力,充滿激情,但在技術(shù)上也許還不夠成熟。此時期黑客圈子里販賣漏洞、惡意軟件的現(xiàn)象開始升溫,同時因為黑客群體的良莠不齊,也開始出現(xiàn)以贏利為目的的攻擊行為,黑色產(chǎn)業(yè)鏈逐漸成型。

最后是黑暗時代,這個階段從幾年前開始一直延續(xù)到今天,也許還將繼續(xù)下去。在這個時期黑客組織也遵循著社會發(fā)展規(guī)律,優(yōu)勝劣汰,大多數(shù)的黑客組織沒有堅持下來。在上一個時期非常流行的黑客技術(shù)論壇越來越缺乏人氣,最終走向沒落。所有門戶型的漏洞披露站點,也不再公布任何漏洞相關(guān)的技術(shù)細(xì)節(jié)。

伴隨著安全產(chǎn)業(yè)的發(fā)展,黑客的功利性越來越強(qiáng)。黑色產(chǎn)業(yè)鏈開始成熟,這個地下產(chǎn)業(yè)每年都會給互聯(lián)網(wǎng)造成數(shù)十億的損失。而在上一個時期技術(shù)還不成熟的黑客們,凡是堅持下來的,都已經(jīng)成長為安全領(lǐng)域的高級人才,有的在安全公司貢獻(xiàn)著自己的專業(yè)技能,有的則帶著非常強(qiáng)的技術(shù)進(jìn)入了黑色產(chǎn)業(yè)。此時期的黑客群體因為互相之間缺失信任已經(jīng)不再具有開放和分享的精神,最為純粹的黑客精神實質(zhì)上已經(jīng)死亡。

整個互聯(lián)網(wǎng)籠罩在黑色產(chǎn)業(yè)鏈的陰影之下,每年數(shù)十億的經(jīng)濟(jì)損失和數(shù)千萬的網(wǎng)民受害,以及黑客精神的死亡,使得我們沒有理由不把此時稱為黑暗時代。也許黑客精神所代表的Open、Free、Share,真的一去不復(fù)返了!

1.1.2 黑客技術(shù)的發(fā)展歷程

從黑客技術(shù)發(fā)展的角度看,在早期,黑客攻擊的目標(biāo)以系統(tǒng)軟件居多。一方面,是由于這個時期的Web技術(shù)發(fā)展還遠(yuǎn)遠(yuǎn)不成熟;另一方面,則是因為通過攻擊系統(tǒng)軟件,黑客們往往能夠直接獲取root權(quán)限。這段時期,涌現(xiàn)出了非常多的經(jīng)典漏洞以及“exploit”。比如著名的黑客組織TESO,就曾經(jīng)編寫過一個攻擊SSH的exploit,并公然在exploit的banner中宣稱曾經(jīng)利用這個exploit入侵過cia.gov(美國中央情報局)。

下面是這個exploithttp://staff.washington.edu/dittrich/misc/ssh-analysis.txt的一些信息。

    root@plac /bin >> ./ssh

    linux/x86 sshd1 exploit by zip/TESO (zip@james.kalifornia.com) - ripped from
    openssh 2.2.0 src
    greets: mray, random, big t, sh1fty, scut, dvorak
    ps. this sploit already owned cia.gov :/

    **please pick a type**

    Usage: ./ssh host [options]
    Options:
      -p port
      -b baseBase address to start bruteforcing distance, by default 0x1800,
    goes as high as 0x10000
      -t type
      -d          debug mode
      -o     Add this to delta_min

    types:

    0: linux/x86 ssh.com 1.2.26-1.2.31 rhl
    1: linux/x86 openssh 1.2.3 (maybe others)
    2: linux/x86 openssh 2.2.0p1 (maybe others)
    3: freebsd 4.x, ssh.com 1.2.26-1.2.31 rhl

有趣的是,這個exploit還曾經(jīng)出現(xiàn)在著名電影《黑客帝國2》中:

電影《黑客帝國2》

放大屏幕上的文字可以看到:

電影《黑客帝國2》中使用的著名exploit

在早期互聯(lián)網(wǎng)中,Web并非互聯(lián)網(wǎng)的主流應(yīng)用,相對來說,基于SMTP、POP3、FTP、IRC等協(xié)議的服務(wù)擁有著絕大多數(shù)的用戶。因此黑客們主要的攻擊目標(biāo)是網(wǎng)絡(luò)、操作系統(tǒng)以及軟件等領(lǐng)域,Web安全領(lǐng)域的攻擊與防御技術(shù)均處于非常原始的階段。

相對于那些攻擊系統(tǒng)軟件的exploit而言,基于Web的攻擊,一般只能讓黑客獲得一個較低權(quán)限的賬戶,對黑客的吸引力遠(yuǎn)遠(yuǎn)不如直接攻擊系統(tǒng)軟件。

但是時代在發(fā)展,防火墻技術(shù)的興起改變了互聯(lián)網(wǎng)安全的格局。尤其是以Cisco、華為等為代表的網(wǎng)絡(luò)設(shè)備廠商,開始在網(wǎng)絡(luò)產(chǎn)品中更加重視網(wǎng)絡(luò)安全,最終改變了互聯(lián)網(wǎng)安全的走向。防火墻、ACL技術(shù)的興起,使得直接暴露在互聯(lián)網(wǎng)上的系統(tǒng)得到了保護(hù)。

比如一個網(wǎng)站的數(shù)據(jù)庫,在沒有保護(hù)的情況下,數(shù)據(jù)庫服務(wù)端口是允許任何人隨意連接的;在有了防火墻的保護(hù)后,通過ACL可以控制只允許信任來源的訪問。這些措施在很大程度上保證了系統(tǒng)軟件處于信任邊界之內(nèi),從而杜絕了大部分的攻擊來源。

2003年的沖擊波蠕蟲是一個里程碑式的事件,這個針對Windows操作系統(tǒng)RPC服務(wù)(運行在445端口)的蠕蟲,在很短的時間內(nèi)席卷了全球,造成了數(shù)百萬臺機(jī)器被感染,損失難以估量。在此次事件后,網(wǎng)絡(luò)運營商們很堅決地在骨干網(wǎng)絡(luò)上屏蔽了135、445等端口的連接請求。此次事件之后,整個互聯(lián)網(wǎng)對于安全的重視達(dá)到了一個空前的高度。

運營商、防火墻對于網(wǎng)絡(luò)的封鎖,使得暴露在互聯(lián)網(wǎng)上的非Web服務(wù)越來越少,且Web技術(shù)的成熟使得Web應(yīng)用的功能越來越強(qiáng)大,最終成為了互聯(lián)網(wǎng)的主流。黑客們的目光,也漸漸轉(zhuǎn)移到了Web這塊大蛋糕上。

實際上,在互聯(lián)網(wǎng)安全領(lǐng)域所經(jīng)歷的這個階段,還有另外一個重要的分支,即桌面軟件安全,或者叫客戶端軟件安全。其代表是瀏覽器攻擊。一個典型的攻擊場景是,黑客構(gòu)造一個惡意網(wǎng)頁,誘使用戶使用瀏覽器訪問該網(wǎng)頁,利用瀏覽器中存在的某些漏洞,比如一個緩沖區(qū)溢出漏洞,執(zhí)行shellcode,通常是下載一個木馬并在用戶機(jī)器里執(zhí)行。常見的針對桌面軟件的攻擊目標(biāo),還包括微軟的Office系列軟件、Adobe Acrobat Reader、多媒體播放軟件、壓縮軟件等裝機(jī)量大的流行軟件,都曾經(jīng)成為黑客們的最愛。但是這種攻擊,和本書要討論的Web安全還是有著本質(zhì)的區(qū)別,所以即使瀏覽器安全是Web安全的重要組成部分,但在本書中,也只會討論瀏覽器和Web安全有關(guān)的部分。

1.1.3 Web安全的興起

Web攻擊技術(shù)的發(fā)展也可以分為幾個階段。在Web 1.0時代,人們更多的是關(guān)注服務(wù)器端動態(tài)腳本的安全問題,比如將一個可執(zhí)行腳本(俗稱webshell)上傳到服務(wù)器上,從而獲得權(quán)限。動態(tài)腳本語言的普及,以及Web技術(shù)發(fā)展初期對安全問題認(rèn)知的不足導(dǎo)致很多“血案”的發(fā)生,同時也遺留下很多歷史問題,比如PHP語言至今仍然只能靠較好的代碼規(guī)范來保證沒有文件包含漏洞,而無法從語言本身杜絕此類安全問題的發(fā)生。

SQL注入的出現(xiàn)是Web安全史上的一個里程碑,它最早出現(xiàn)大概是在1999年,并很快就成為Web安全的頭號大敵。就如同緩沖區(qū)溢出出現(xiàn)時一樣,程序員們不得不日以繼夜地去修改程序中存在的漏洞。黑客們發(fā)現(xiàn)通過SQL注入攻擊,可以獲取很多重要的、敏感的數(shù)據(jù),甚至能夠通過數(shù)據(jù)庫獲取系統(tǒng)訪問權(quán)限,這種效果并不比直接攻擊系統(tǒng)軟件差,Web攻擊一下子就流行起來。SQL注入漏洞至今仍然是Web安全領(lǐng)域中的一個重要組成部分。

XSS(跨站腳本攻擊)的出現(xiàn)則是Web安全史上的另一個里程碑。實際上,XSS的出現(xiàn)時間和SQL注入差不多,但是真正引起人們重視則是在大概2003年以后。在經(jīng)歷了MySpace的XSS蠕蟲事件后,安全界對XSS的重視程度提高了很多,OWASP 2007 TOP 10威脅甚至把XSS排在榜首。

伴隨著Web 2.0的興起,XSS、CSRF等攻擊已經(jīng)變得更為強(qiáng)大。Web攻擊的思路也從服務(wù)器端轉(zhuǎn)向了客戶端,轉(zhuǎn)向了瀏覽器和用戶。黑客們天馬行空的思路,覆蓋了Web的每一個環(huán)節(jié),變得更加的多樣化,這些安全問題,在本書后續(xù)的章節(jié)中會深入地探討。

Web技術(shù)發(fā)展到今天,構(gòu)建出了豐富多彩的互聯(lián)網(wǎng)。互聯(lián)網(wǎng)業(yè)務(wù)的蓬勃發(fā)展,也催生出了許多新興的腳本語言,比如Python、Ruby、NodeJS等,敏捷開發(fā)成為互聯(lián)網(wǎng)的主旋律。而手機(jī)技術(shù)、移動互聯(lián)網(wǎng)的興起,也給HTML 5帶來了新的機(jī)遇和挑戰(zhàn)。與此同時,Web安全技術(shù),也將緊跟著互聯(lián)網(wǎng)發(fā)展的腳步,不斷地演化出新的變化。

1.2 黑帽子,白帽子

正如一個硬幣有兩面一樣,“黑客”也有好壞之分。在黑客的世界中,往往用帽子的顏色來比喻黑客的好壞。白帽子,則是指那些精通安全技術(shù),但是工作在反黑客領(lǐng)域的專家們;而黑帽子,則是指利用黑客技術(shù)造成破壞,甚至進(jìn)行網(wǎng)絡(luò)犯罪的群體。

同樣是研究安全,白帽子和黑帽子在工作時的心態(tài)是完全不同的。

對于黑帽子來說,只要能夠找到系統(tǒng)的一個弱點,就可以達(dá)到入侵系統(tǒng)的目的;而對于白帽子來說,必須找到系統(tǒng)的所有弱點,不能有遺漏,才能保證系統(tǒng)不會出現(xiàn)問題。這種差異是由于工作環(huán)境與工作目標(biāo)的不同所導(dǎo)致的。白帽子一般為企業(yè)或安全公司服務(wù),工作的出發(fā)點就是要解決所有的安全問題,因此所看所想必然要求更加的全面、宏觀;黑帽子的主要目的是要入侵系統(tǒng),找到對他們有價值的數(shù)據(jù),因此黑帽子只需要以點突破,找到對他們最有用的一點,以此滲透,因此思考問題的出發(fā)點必然是有選擇性的、微觀的。

從對待問題的角度來看,黑帽子為了完成一次入侵,需要利用各種不同漏洞的組合來達(dá)到目的,是在不斷地組合問題;而白帽子在設(shè)計解決方案時,如果只看到各種問題組合后產(chǎn)生的效果,就會把事情變復(fù)雜,難以細(xì)致入微地解決根本問題,所以白帽子必然是在不斷地分解問題,再對分解后的問題逐個予以解決。

這種定位的不對稱,也導(dǎo)致了白帽子的安全工作比較難做。“破壞永遠(yuǎn)比建設(shè)容易”,但凡事都不是絕對的。要如何扭轉(zhuǎn)這種局面呢?一般來說,白帽子選擇的方法,是克服某種攻擊方法,而并非抵御單次的攻擊。比如設(shè)計一個解決方案,在特定環(huán)境下能夠抵御所有已知的和未知的SQL Injection問題。假設(shè)這個方案的實施周期是3個月,那么執(zhí)行3個月后,所有的SQL Injection問題都得到了解決,也就意味著黑客再也無法利用SQL Injection這一可能存在的弱點入侵網(wǎng)站了。如果做到了這一點,那么白帽子們就在SQL Injection的局部對抗中化被動為主動了。

但這一切都是理想狀態(tài),在現(xiàn)實世界中,存在著各種各樣不可回避的問題。工程師們很喜歡一句話:“No Patch For Stupid! ”,在安全領(lǐng)域也普遍認(rèn)為:“最大的漏洞就是人!”。寫得再好的程序,在有人參與的情況下,就可能會出現(xiàn)各種各樣不可預(yù)知的情況,比如管理員的密碼有可能泄露,程序員有可能關(guān)掉了安全的配置參數(shù),等等。安全問題往往發(fā)生在一些意想不到的地方。

另一方面,防御技術(shù)在不斷完善的同時,攻擊技術(shù)也在不斷地發(fā)展。這就像一場軍備競賽,看誰跑在前面。白帽子們剛把某一種漏洞全部堵上,黑帽子們轉(zhuǎn)眼又會玩出新花樣。誰能在技術(shù)上領(lǐng)先,誰就能占據(jù)主動。互聯(lián)網(wǎng)技術(shù)日新月異,在新技術(shù)領(lǐng)域的發(fā)展中,也存在著同樣的博弈過程。可現(xiàn)狀是,如果新技術(shù)不在一開始就考慮安全設(shè)計的話,防御技術(shù)就必然會落后于攻擊技術(shù),導(dǎo)致歷史不斷地重復(fù)。

1.3 返璞歸真,揭秘安全的本質(zhì)

講了很多題外話,最終回到正題上。這是一本講Web安全的書,在本書中除了講解必要的攻擊技術(shù)原理之外,最終重心還是要放在防御的思路和實現(xiàn)的技術(shù)上。

在進(jìn)行具體技術(shù)的講解之前,我們需要先清楚地認(rèn)識到“安全的本質(zhì)”,或者說,“安全問題的本質(zhì)”。

安全是什么?什么樣的情況下會產(chǎn)生安全問題?我們要如何看待安全問題?只有搞明白了這些最基本的問題,才能明白一切防御技術(shù)的出發(fā)點,才能明白為什么我們要這樣做,要那樣做。

在武俠小說中,一個真正的高手,對武功有著最透徹、最本質(zhì)的理解,達(dá)到了返璞歸真的境界。在安全領(lǐng)域,筆者認(rèn)為搞明白了安全的本質(zhì),就好比學(xué)會了“獨孤九劍”,天下武功萬變不離其宗,遇到任何復(fù)雜的情況都可以輕松應(yīng)對,設(shè)計任何的安全方案也都可以信手拈來了。

那么,一個安全問題是如何產(chǎn)生的呢?我們不妨先從現(xiàn)實世界入手。火車站、機(jī)場里,在乘客們開始正式旅程之前,都有一個必要的程序:安全檢查。機(jī)場的安全檢查,會掃描乘客的行李箱,檢查乘客身上是否攜帶了打火機(jī)、可燃液體等危險物品。抽象地說,這種安全檢查,就是過濾掉有害的、危險的東西。因為在飛行的過程中,飛機(jī)遠(yuǎn)離地面,如果發(fā)生危險,將會直接危害到乘客們的生命安全。因此,飛機(jī)是一個高度敏感和重要的區(qū)域,任何有危害的物品都不應(yīng)該進(jìn)入這一區(qū)域。為達(dá)到這一目標(biāo),登機(jī)前的安全檢查就是一個非常有必要的步驟。

從安全的角度來看,我們將不同重要程度的區(qū)域劃分出來:

安全檢查的過程按照需要進(jìn)行過濾

通過一個安全檢查(過濾、凈化)的過程,可以梳理未知的人或物,使其變得可信任。被劃分出來的具有不同信任級別的區(qū)域,我們稱為信任域,劃分兩個不同信任域之間的邊界,我們稱為信任邊界。

數(shù)據(jù)從高等級的信任域流向低等級的信任域,是不需要經(jīng)過安全檢查的;數(shù)據(jù)從低等級的信任域流向高等級的信任域,則需要經(jīng)過信任邊界的安全檢查。

我們在機(jī)場通過安檢后,想要從候機(jī)廳出來,是不需要做檢查的;但是想要再回到候機(jī)廳,則需要再做一次安全檢查,就是這個道理。

筆者認(rèn)為,安全問題的本質(zhì)是信任的問題。

一切的安全方案設(shè)計的基礎(chǔ),都是建立在信任關(guān)系上的。我們必須相信一些東西,必須有一些最基本的假設(shè),安全方案才能得以建立;如果我們否定一切,安全方案就會如無源之水,無根之木,無法設(shè)計,也無法完成。

舉例來說,假設(shè)我們有份很重要的文件要好好保管起來,能想到的一個方案是把文件“鎖”到抽屜里。這里就包含了幾個基本的假設(shè),首先,制作這把鎖的工匠是可以信任的,他沒有私自藏一把鑰匙;其次,制作抽屜的工匠沒有私自給抽屜裝一個后門;最后,鑰匙還必須要保管在一個不會出問題的地方,或者交給值得信任的人保管。反之,如果我們一切都不信任,那么也就不可能認(rèn)為文件放在抽屜里是安全的。

當(dāng)制鎖的工匠無法打開鎖時,文件才是安全的,這是我們的假設(shè)前提之一。但是如果那個工匠私自藏有一把鑰匙,那么這份文件也就不再安全了。這個威脅存在的可能性,依賴于對工匠的信任程度。如果我們信任工匠,那么在這個假設(shè)前提下,我們就能確定文件的安全性。這種對條件的信任程度,是確定對象是否安全的基礎(chǔ)。

在現(xiàn)實生活中,我們很少設(shè)想最極端的前提條件,因為極端的條件往往意味者小概率以及高成本,因此在成本有限的情況下,我們往往會根據(jù)成本來設(shè)計安全方案,并將一些可能性較大的條件作為決策的主要依據(jù)。

比如在設(shè)計物理安全時,根據(jù)不同的地理位置、不同的政治環(huán)境等,需要考慮臺風(fēng)、地震、戰(zhàn)爭等因素。但在考慮、設(shè)計這些安全方案時,根據(jù)其發(fā)生的可能性,需要有不同的側(cè)重點。比如在大陸深處,考慮臺風(fēng)的因素則顯得不太實際;同樣的道理,在大陸板塊穩(wěn)定的地區(qū),考慮地震的因素也會帶來較高的成本。而極端的情況比如“彗星撞擊地球后如何保證機(jī)房不受影響”的問題,一般都不在考慮之中,因為發(fā)生的可能性太小。

從另一個角度來說,一旦我們作為決策依據(jù)的條件被打破、被繞過,那么就會導(dǎo)致安全假設(shè)的前提條件不再可靠,變成一個偽命題。因此,把握住信任條件的度,使其恰到好處,正是設(shè)計安全方案的難點所在,也是安全這門學(xué)問的藝術(shù)魅力所在。

1.4 破除迷信,沒有銀彈

在解決安全問題的過程中,不可能一勞永逸,也就是說“沒有銀彈”。

一般來說,人們都會討厭麻煩的事情,在潛意識里希望能夠讓麻煩越遠(yuǎn)越好。而安全,正是一件麻煩的事情,而且是無法逃避的麻煩。任何人想要一勞永逸地解決安全問題,都屬于一相情愿,是“自己騙自己”,是不現(xiàn)實的。

安全是一個持續(xù)的過程。

自從互聯(lián)網(wǎng)有了安全問題以來,攻擊和防御技術(shù)就在不斷碰撞和對抗的過程中得到發(fā)展。從微觀上來說,在某一時期可能某一方占了上風(fēng);但是從宏觀上來看,某一時期的攻擊或防御技術(shù),都不可能永遠(yuǎn)有效,永遠(yuǎn)用下去。這是因為防御技術(shù)在發(fā)展的同時,攻擊技術(shù)也在不斷發(fā)展,兩者是互相促進(jìn)的辯證關(guān)系。以不變的防御手段對抗不斷發(fā)展的攻擊技術(shù),就犯了刻舟求劍的錯誤。在安全的領(lǐng)域中,沒有銀彈。

很多安全廠商在推銷自己產(chǎn)品時,會向用戶展示一些很美好的藍(lán)圖,似乎他們的產(chǎn)品無所不能,購買之后用戶就可以睡得安穩(wěn)了。但實際上,安全產(chǎn)品本身也需要不斷地升級,也需要有人來運營。產(chǎn)品本身也需要一個新陳代謝的過程,否則就會被淘汰。在現(xiàn)代的互聯(lián)網(wǎng)產(chǎn)品中,自動升級功能已經(jīng)成為一個標(biāo)準(zhǔn)配置,一個有活力的產(chǎn)品總是會不斷地改進(jìn)自身。

微軟在發(fā)布Vista時,曾信誓旦旦地保證這是有史以來最安全的操作系統(tǒng)。我們看到了微軟的努力,在Vista下的安全問題確實比它的前輩們(Windows XP、Windows 2000、Windows 2003等)少了許多,尤其是高危的漏洞。但即便如此,在2008年的Pwn2own競賽上,Vista也被黑客們攻擊成功。Pwn2own競賽是每年舉行的讓黑客們?nèi)我夤舨僮飨到y(tǒng)的一次盛會,一般黑客們都會提前準(zhǔn)備好0day漏洞的攻擊程序,以求在Pwn2own上一舉奪魁。

黑客們在不斷地研究和尋找新的攻擊技術(shù),作為防御的一方,沒有理由不持續(xù)跟進(jìn)。微軟近幾年在產(chǎn)品的安全中做得越來越好,其所推崇的安全開發(fā)流程,將安全檢查貫穿于整個軟件生命周期中,經(jīng)過實踐檢驗,證明這是一條可行的道路。對每一個產(chǎn)品,都要持續(xù)地實施嚴(yán)格的安全檢查,這是微軟通過自身的教訓(xùn)傳授給業(yè)界的寶貴經(jīng)驗。而安全檢查本身也需要不斷更新,增加針對新型攻擊方式的檢測與防御方案。

1.5 安全三要素

既然安全方案的設(shè)計與實施過程中沒有銀彈,注定是一個持續(xù)進(jìn)行的過程,那么我們該如何開始呢?其實安全方案的設(shè)計也有著一定的思路與方法可循,借助這些方法,能夠理清我們的思路,幫助我們設(shè)計出合理、優(yōu)秀的解決方案。

因為信任關(guān)系被破壞,從而產(chǎn)生了安全問題。我們可以通過信任域的劃分、信任邊界的確定,來發(fā)現(xiàn)問題是在何處產(chǎn)生的。這個過程可以讓我們明確目標(biāo),那接下來該怎么做呢?

在設(shè)計安全方案之前,要正確、全面地看待安全問題。

要全面地認(rèn)識一個安全問題,我們有很多種辦法,但首先要理解安全問題的組成屬性。前人通過無數(shù)實踐,最后將安全的屬性總結(jié)為安全三要素,簡稱CIA

安全三要素是安全的基本組成元素,分別是機(jī)密性(Confidentiality)、完整性(Integrity)、可用性(Availability)

機(jī)密性要求保護(hù)數(shù)據(jù)內(nèi)容不能泄露,加密是實現(xiàn)機(jī)密性要求的常見手段。

比如在前文的例子中,如果文件不是放在抽屜里,而是放在一個透明的玻璃盒子里,那么雖然外人無法直接取得文件,但因為玻璃盒子是透明的,文件內(nèi)容可能還是會被人看到,所以不符合機(jī)密性要求。但是如果給文件增加一個封面,掩蓋了文件內(nèi)容,那么也就起到了隱藏的效果,從而滿足了機(jī)密性要求。可見,我們在選擇安全方案時,需要靈活變通,因地制宜,沒有一成不變的方案。

完整性則要求保護(hù)數(shù)據(jù)內(nèi)容是完整、沒有被篡改的。常見的保證一致性的技術(shù)手段是數(shù)字簽名。

傳說清朝康熙皇帝的遺詔,寫的是“傳位十四子”,被當(dāng)時還是四阿哥的胤禛篡改了遺詔,變成了“傳位于四子”。姑且不論傳說的真實性,在故事中,對這份遺詔的保護(hù)顯然沒有達(dá)到完整性要求。如果在當(dāng)時有數(shù)字簽名等技術(shù),遺詔就很難被篡改。從這個故事中也可以看出數(shù)據(jù)的完整性、一致性的重要意義。

可用性要求保護(hù)資源是“隨需而得”。

假設(shè)一個停車場里有100個車位,在正常情況下,可以停100輛車。但是在某一天,有個壞人搬了100塊大石頭,把每個車位都占用了,停車場無法再提供正常服務(wù)。在安全領(lǐng)域中這種攻擊叫做拒絕服務(wù)攻擊,簡稱DoS(Denial of Service)。拒絕服務(wù)攻擊破壞的是安全的可用性。

在安全領(lǐng)域中,最基本的要素就是這三個,后來還有人想擴(kuò)充這些要素,增加了諸如可審計性、不可抵賴性等,但最最重要的還是以上三個要素。在設(shè)計安全方案時,也要以這三個要素為基本的出發(fā)點,去全面地思考所面對的問題。

1.6 如何實施安全評估

有了前面的基礎(chǔ),我們就可以正式開始分析并解決安全問題了。一個安全評估的過程,可以簡單地分為4個階段:資產(chǎn)等級劃分、威脅分析、風(fēng)險分析、確認(rèn)解決方案。

安全評估的過程

一般來說,按照這個過程來實施安全評估,在結(jié)果上不會出現(xiàn)較大的問題。這個實施的過程是層層遞進(jìn)的,前后之間有因果關(guān)系。

如果面對的是一個尚未評估的系統(tǒng),那么應(yīng)該從第一個階段開始實施;如果是由專職的安全團(tuán)隊長期維護(hù)的系統(tǒng),那么有些階段可以只實施一次。在這幾個階段中,上一個階段將決定下一個階段的目標(biāo),需要實施到什么程度。

1.6.1 資產(chǎn)等級劃分

資產(chǎn)等級劃分是所有工作的基礎(chǔ),這項工作能夠幫助我們明確目標(biāo)是什么,要保護(hù)什么。

我們前面提到安全三要素時,機(jī)密性和完整性都是與數(shù)據(jù)相關(guān)的,在可用性的定義里,筆者則用到了“資源”一詞。“資源”這個概念描述的范圍比數(shù)據(jù)要更加廣闊,但很多時候,資源的可用性也可以理解為數(shù)據(jù)的可用性。

在互聯(lián)網(wǎng)的基礎(chǔ)設(shè)施已經(jīng)比較完善的今天,互聯(lián)網(wǎng)的核心其實是由用戶數(shù)據(jù)驅(qū)動的——用戶產(chǎn)生業(yè)務(wù),業(yè)務(wù)產(chǎn)生數(shù)據(jù)。互聯(lián)網(wǎng)公司除了擁有一些固定資產(chǎn),如服務(wù)器等死物外,最核心的價值就是其擁有的用戶數(shù)據(jù),所以——

互聯(lián)網(wǎng)安全的核心問題,是數(shù)據(jù)安全的問題。

這與我們做資產(chǎn)評估又有什么關(guān)系呢?有,因為對互聯(lián)網(wǎng)公司擁有的資產(chǎn)進(jìn)行等級劃分,就是對數(shù)據(jù)做等級劃分。有的公司最關(guān)心的是客戶數(shù)據(jù),有的公司最關(guān)心的是員工資料信息,根據(jù)各自業(yè)務(wù)的不同,側(cè)重點也不同。做資產(chǎn)等級劃分的過程,需要與各個業(yè)務(wù)部門的負(fù)責(zé)人一一溝通,了解公司最重要的資產(chǎn)是什么,他們最看重的數(shù)據(jù)是什么。通過訪談的形式,安全部門才能熟悉、了解公司的業(yè)務(wù),公司所擁有的數(shù)據(jù),以及不同數(shù)據(jù)的重要程度,為后續(xù)的安全評估過程指明方向。

當(dāng)完成資產(chǎn)等級劃分后,對要保護(hù)的目標(biāo)已經(jīng)有了一個大概的了解,接下來就是要劃分信任域和信任邊界了。通常我們用一種最簡單的劃分方式,就是從網(wǎng)絡(luò)邏輯上來劃分。比如最重要的數(shù)據(jù)放在數(shù)據(jù)庫里,那么把數(shù)據(jù)庫的服務(wù)器圈起來;Web應(yīng)用可以從數(shù)據(jù)庫中讀/寫數(shù)據(jù),并對外提供服務(wù),那再把Web服務(wù)器圈起來;最外面是不可信任的Internet。

簡單網(wǎng)站信任模型

這是最簡單的例子,在實際中會遇到比這復(fù)雜許多的情況。比如同樣是兩個應(yīng)用,互相之間存在數(shù)據(jù)交互業(yè)務(wù),那么就要考慮這里的數(shù)據(jù)交互對于各自應(yīng)用來說是否是可信的,是否應(yīng)該在兩個應(yīng)用之間劃一個邊界,然后對流經(jīng)邊界的數(shù)據(jù)做安全檢查。

1.6.2 威脅分析

信任域劃好之后,我們?nèi)绾尾拍艽_定危險來自哪里呢?在安全領(lǐng)域里,我們把可能造成危害的來源稱為威脅(Threat),而把可能會出現(xiàn)的損失稱為風(fēng)險(Risk)。風(fēng)險一定是和損失聯(lián)系在一起的,很多專業(yè)的安全工程師也經(jīng)常把這兩個概念弄混,在寫文檔時張冠李戴。現(xiàn)在把這兩個概念區(qū)分好,有助于我們接下來要提到的“威脅建模”和“風(fēng)險分析”兩個階段,這兩個階段的聯(lián)系是很緊密的。

什么是威脅分析?威脅分析就是把所有的威脅都找出來。怎么找?一般是采用頭腦風(fēng)暴法。當(dāng)然,也有一些比較科學(xué)的方法,比如使用一個模型,幫助我們?nèi)ハ耄谀男┓矫嬗锌赡軙嬖谕{,這個過程能夠避免遺漏,這就是威脅建模。

在本書中介紹一種威脅建模的方法,它最早是由微軟提出的,叫做STRIDE模型。

STRIDE是6個單詞的首字母縮寫,我們在分析威脅時,可以從以下6個方面去考慮。

在進(jìn)行威脅分析時,要盡可能地不遺漏威脅,頭腦風(fēng)暴的過程可以確定攻擊面(Attack Surface)。

在維護(hù)系統(tǒng)安全時,最讓安全工程師沮喪的事情就是花費很多的時間與精力實施安全方案,但是攻擊者卻利用了事先完全沒有想到的漏洞(漏洞的定義:系統(tǒng)中可能被威脅利用以造成危害的地方。)完成入侵。這往往就是由于在確定攻擊面時,想的不夠全面而導(dǎo)致的。

以前有部老電影叫做《智取華山》,是根據(jù)真實事件改編的。1949年5月中旬,打響了“陜中戰(zhàn)役”,國民黨保安第6旅旅長兼第8區(qū)專員韓子佩率殘部400余人逃上華山,企圖憑借“自古華山一條道”的天險負(fù)隅頑抗。路東總隊決定派參謀劉吉堯帶偵察小分隊前往偵察,劉吉堯率領(lǐng)小分隊,在當(dāng)?shù)卮迕竦膸ьI(lǐng)下,找到了第二條路:爬懸崖!克服種種困難,最終順利地完成了任務(wù)。戰(zhàn)后,劉吉堯光榮地出席了全國英模代表大會,并被授予“全國特等戰(zhàn)斗英雄”榮譽(yù)稱號。

我們用安全眼光來看這次戰(zhàn)斗。國民黨部隊在進(jìn)行“威脅分析”時,只考慮到“自古華山一條道”,所以在正路上布重兵,而完全忽略了其他的可能。他們“相信”其他道路是不存在的,這是他們實施安全方案的基礎(chǔ),而一旦這個信任基礎(chǔ)不存在了,所有的安全方案都將化作浮云,從而被共產(chǎn)黨的部隊擊敗。

所以威脅分析是非常重要的一件事情,很多時候還需要經(jīng)常回顧和更新現(xiàn)有的模型。可能存在很多威脅,但并非每個威脅都會造成難以承受的損失。一個威脅到底能夠造成多大的危害,如何去衡量它?這就要考慮到風(fēng)險了。我們判斷風(fēng)險高低的過程,就是風(fēng)險分析的過程。在“風(fēng)險分析”這個階段,也有模型可以幫助我們進(jìn)行科學(xué)的思考。

1.6.3 風(fēng)險分析

風(fēng)險由以下因素組成:

    Risk = Probability * Damage Potential

影響風(fēng)險高低的因素,除了造成損失的大小外,還需要考慮到發(fā)生的可能性。地震的危害很大,但是地震、火山活動一般是在大陸板塊邊緣頻繁出現(xiàn),比如日本、印尼就處于這些地理位置,因此地震頻發(fā);而在大陸板塊中心,若是地質(zhì)結(jié)構(gòu)以整塊的巖石為主,則不太容易發(fā)生地震,因此地震的風(fēng)險就要小很多。我們在考慮安全問題時,要結(jié)合具體情況,權(quán)衡事件發(fā)生的可能性,才能正確地判斷出風(fēng)險。

如何更科學(xué)地衡量風(fēng)險呢?這里再介紹一個DREAD模型,它也是由微軟提出的。DREAD也是幾個單詞的首字母縮寫,它指導(dǎo)我們應(yīng)該從哪些方面去判斷一個威脅的風(fēng)險程度。

在DREAD模型里,每一個因素都可以分為高、中、低三個等級。在上表中,高、中、低三個等級分別以3、2、1的分?jǐn)?shù)代表其權(quán)重值,因此,我們可以具體計算出某一個威脅的風(fēng)險值。

以《智取華山》為例,如果國民黨在威脅建模后發(fā)現(xiàn)存在兩個主要威脅:第一個威脅是從正面入口強(qiáng)攻,第二個威脅是從后山小路爬懸崖上來。那么,這兩個威脅對應(yīng)的風(fēng)險分別計算如下:

走正面的入口:

    Risk = D(3) + R(3) + E(3) + A(3) + D(3) = 3+3+3+3+3=15

走后山小路:

    Risk = D(3) + R(1) + E(1) + A(3) + D(1) = 3+1+1+3+1=9

如果我們把風(fēng)險高低定義如下:

    高危:12~15分        中危:8~11分        低危:0~7分

那么,正面入口是最高危的,必然要派重兵把守;而后山小路竟然是中危的,因此也不能忽視。之所以會被這個模型判斷為中危的原因,就在于一旦被突破,造成的損失太大,失敗不起,所以會相應(yīng)地提高該風(fēng)險值。

介紹完威脅建模和風(fēng)險分析的模型后,我們對安全評估的整體過程應(yīng)該有了一個大致的了解。在任何時候都應(yīng)該記住——模型是死的,人是活的,再好的模型也是需要人來使用的,在確定攻擊面,以及判斷風(fēng)險高低時,都需要有一定的經(jīng)驗,這也是安全工程師的價值所在。類似STRIDE和DREAD的模型可能還有很多,不同的標(biāo)準(zhǔn)會對應(yīng)不同的模型,只要我們覺得這些模型是科學(xué)的,能夠幫到我們,就可以使用。但模型只能起到一個輔助的作用,最終做出決策的還是人。

1.6.4 設(shè)計安全方案

安全評估的產(chǎn)出物,就是安全解決方案。解決方案一定要有針對性,這種針對性是由資產(chǎn)等級劃分、威脅分析、風(fēng)險分析等階段的結(jié)果給出的。

設(shè)計解決方案不難,難的是如何設(shè)計一個好的解決方案。設(shè)計一個好的解決方案,是真正考驗安全工程師水平的時候。

很多人認(rèn)為,安全和業(yè)務(wù)是沖突的,因為往往為了安全,要犧牲業(yè)務(wù)的一些易用性或者性能,筆者不太贊同這種觀點。從產(chǎn)品的角度來說,安全也應(yīng)該是產(chǎn)品的一種屬性。一個從未考慮過安全的產(chǎn)品,至少是不完整的。

比如,我們要評價一個杯子是否好用,除了它能裝水,能裝多少水外,還要思考這個杯子內(nèi)壁的材料是否會溶解在水里,是否會有毒,在高溫時會不會熔化,在低溫時是否易碎,這些問題都直接影響用戶使用杯子的安全性。

對于互聯(lián)網(wǎng)來說,安全是要為產(chǎn)品的發(fā)展與成長保駕護(hù)航的。我們不能使用“粗暴”的安全方案去阻礙產(chǎn)品的正常發(fā)展,所以應(yīng)該形成這樣一種觀點:沒有不安全的業(yè)務(wù),只有不安全的實現(xiàn)方式。產(chǎn)品需求,尤其是商業(yè)需求,是用戶真正想要的東西,是業(yè)務(wù)的意義所在,在設(shè)計安全方案時應(yīng)該盡可能地不要改變商業(yè)需求的初衷。

作為安全工程師,要想的就是如何通過簡單而有效的方案,解決遇到的安全問題。安全方案必須能夠有效抵抗威脅,但同時不能過多干涉正常的業(yè)務(wù)流程,在性能上也不能拖后腿。

好的安全方案對用戶應(yīng)該是透明的,盡可能地不要改變用戶的使用習(xí)慣。

微軟在推出Windows Vista時,有一個新增的功能叫UAC,每當(dāng)系統(tǒng)里的軟件有什么敏感動作時,UAC就會彈出來詢問用戶是否允許該行為。這個功能在Vista眾多失敗的原因中是被人詬病最多的一個。如果用戶能夠分辨什么樣的行為是安全的,那么還要安全軟件做什么?同樣的問題出現(xiàn)在很多主動防御的桌面安全保護(hù)軟件中,它們動輒彈出個對話框詢問用戶是否允許目標(biāo)的行為,這是非常荒謬的用戶體驗。

好的安全產(chǎn)品或模塊除了要兼顧用戶體驗外,還要易于持續(xù)改進(jìn)。一個好的安全模塊,同時也應(yīng)該是一個優(yōu)秀的程序,從設(shè)計上也需要做到高聚合、低耦合、易于擴(kuò)展。比如Nmap的用戶就可以自己根據(jù)需要寫插件,實現(xiàn)一些更為復(fù)雜的功能,滿足個性化需求。

最終,一個優(yōu)秀的安全方案應(yīng)該具備以下特點:

? 能夠有效解決問題;

? 用戶體驗好;

? 高性能;

? 低耦合;

? 易于擴(kuò)展與升級。

關(guān)于產(chǎn)品安全性的問題,在本書的“互聯(lián)網(wǎng)業(yè)務(wù)安全”一章中還會繼續(xù)深入闡述。

1.7 白帽子兵法

在上節(jié)講述了實施安全評估的基本過程,安全評估最后的產(chǎn)出物就是安全方案,但在具體設(shè)計安全方案時有什么樣的技巧呢?本節(jié)將講述在實戰(zhàn)中可能用到的方法。

1.7.1 Secure By DefauIt原則

在設(shè)計安全方案時,最基本也最重要的原則就是“Secure by Default”。在做任何安全設(shè)計時,都要牢牢記住這個原則。一個方案設(shè)計得是否足夠安全,與有沒有應(yīng)用這個原則有很大的關(guān)系。實際上,“Secure by Default”原則,也可以歸納為白名單、黑名單的思想。如果更多地使用白名單,那么系統(tǒng)就會變得更安全。

1.7.1.1 黑名單、白名單

比如,在制定防火墻的網(wǎng)絡(luò)訪問控制策略時,如果網(wǎng)站只提供Web服務(wù),那么正確的做法是只允許網(wǎng)站服務(wù)器的80和443端口對外提供服務(wù),屏蔽除此之外的其他端口。這是一種“白名單”的做法;如果使用“黑名單”,則可能會出現(xiàn)問題。假設(shè)黑名單的策略是:不允許SSH端口對Internet開放,那么就要審計SSH的默認(rèn)端口:22端口是否開放了Internet。但在實際工作過程中,經(jīng)常會發(fā)現(xiàn)有的工程師為了偷懶或圖方便,私自改變了SSH的監(jiān)聽端口,比如把SSH的端口從22改到了2222,從而繞過了安全策略。

又比如,在網(wǎng)站的生產(chǎn)環(huán)境服務(wù)器上,應(yīng)該限制隨意安裝軟件,而需要制定統(tǒng)一的軟件版本規(guī)范。這個規(guī)范的制定,也可以選擇白名單的思想來實現(xiàn)。按照白名單的思想,應(yīng)該根據(jù)業(yè)務(wù)需求,列出一個允許使用的軟件以及軟件版本的清單,在此清單外的軟件則禁止使用。如果允許工程師在服務(wù)器上隨意安裝軟件的話,則可能會因為安全部門不知道、不熟悉這些軟件而導(dǎo)致一些漏洞,從而擴(kuò)大攻擊面。

在Web安全中,對白名單思想的運用也比比皆是。比如應(yīng)用處理用戶提交的富文本時,考慮到XSS的問題,需要做安全檢查。常見的XSS Filter一般是先對用戶輸入的HTML原文作HTML Parse,解析成標(biāo)簽對象后,再針對標(biāo)簽匹配XSS的規(guī)則。這個規(guī)則列表就是一個黑白名單。如果選擇黑名單的思想,則這套規(guī)則里可能是禁用諸如<script>、<iframe>等標(biāo)簽。但是黑名單可能會有遺漏,比如未來瀏覽器如果支持新的HTML標(biāo)簽,那么此標(biāo)簽可能就不在黑名單之中了。如果選擇白名單的思想,就能避免這種問題——在規(guī)則中,只允許用戶輸入諸如<a>、<img>等需要用到的標(biāo)簽。對于如何設(shè)計一個好的XSS防御方案,在“跨站腳本攻擊”一章中還會詳細(xì)講到,不在此贅述了。

然而,并不是用了白名單就一定安全了。有朋友可能會問,作者剛才講到選擇白名單的思想會更安全,現(xiàn)在又說不一定,這不是自相矛盾嗎?我們可以仔細(xì)分析一下白名單思想的本質(zhì)。在前文中提到:“安全問題的本質(zhì)是信任問題,安全方案也是基于信任來做的”。選擇白名單的思想,基于白名單來設(shè)計安全方案,其實就是信任白名單是好的,是安全的。但是一旦這個信任基礎(chǔ)不存在了,那么安全就蕩然無存。

在Flash跨域訪問請求里,是通過檢查目標(biāo)資源服務(wù)器端的crossdomain.xml文件來驗證是否允許客戶端的Flash跨域發(fā)起請求的,它使用的是白名單的思想。比如下面這個策略文件:

    <cross-domain-policy>
    <allow-access-from domain="*.taobao.com"/>
    <allow-access-from domain="*.taobao.net"/>
    <allow-access-from domain="*.taobaocdn.com"/>
    <allow-access-from domain="*.tbcdn.cn"/>
    <allow-access-from domain="*.allyes.com"/>
    </cross-domain-policy>

指定了只允許特定域的Flash對本域發(fā)起請求。可是如果這個信任列表中的域名變得不可信了,那么問題就會隨之而來。比如:

    <cross-domain-policy>
    <allow-access-from domain="*"/>
    </cross-domain-policy>

通配符“*”,代表來自任意域的Flash都能訪問本域的數(shù)據(jù),因此就造成了安全隱患。所以在選擇使用白名單時,需要注意避免出現(xiàn)類似通配符“*”的問題。

1.7.1.2 最小權(quán)限原則

Secure By Default的另一層含義就是“最小權(quán)限原則”。最小權(quán)限原則也是安全設(shè)計的基本原則之一。最小權(quán)限原則要求系統(tǒng)只授予主體必要的權(quán)限,而不要過度授權(quán),這樣能有效地減少系統(tǒng)、網(wǎng)絡(luò)、應(yīng)用、數(shù)據(jù)庫出錯的機(jī)會。

比如在Linux系統(tǒng)中,一種良好的操作習(xí)慣是使用普通賬戶登錄,在執(zhí)行需要root權(quán)限的操作時,再通過sudo命令完成。這樣能最大化地降低一些誤操作導(dǎo)致的風(fēng)險;同時普通賬戶被盜用后,與root帳戶被盜用所導(dǎo)致的后果是完全不同的。

在使用最小權(quán)限原則時,需要認(rèn)真梳理業(yè)務(wù)所需要的權(quán)限,在很多時候,開發(fā)者并不會意識到業(yè)務(wù)授予用戶的權(quán)限過高。在通過訪談了解業(yè)務(wù)時,可以多設(shè)置一些反問句,比如:您確定您的程序一定需要訪問Internet嗎?通過此類問題,來確定業(yè)務(wù)所需的最小權(quán)限。

1.7.2 縱深防御原則

與Secure by Default一樣,Defense in Depth(縱深防御)也是設(shè)計安全方案時的重要指導(dǎo)思想。

縱深防御包含兩層含義:首先,要在各個不同層面、不同方面實施安全方案,避免出現(xiàn)疏漏,不同安全方案之間需要相互配合,構(gòu)成一個整體;其次,要在正確的地方做正確的事情,即:在解決根本問題的地方實施針對性的安全方案。

某礦泉水品牌曾經(jīng)在廣告中展示了一滴水的生產(chǎn)過程:經(jīng)過十多層的安全過濾,去除有害物質(zhì),最終得到一滴飲用水。這種多層過濾的體系,就是一種縱深防御,是有立體層次感的安全方案。

縱深防御并不是同一個安全方案要做兩遍或多遍,而是要從不同的層面、不同的角度對系統(tǒng)做出整體的解決方案。我們常常聽到“木桶理論”這個詞,說的是一個桶能裝多少水,不是取決于最長的那塊板,而是取決于最短的那塊板,也就是短板。設(shè)計安全方案時最怕出現(xiàn)短板,木桶的一塊塊板子,就是各種具有不同作用的安全方案,這些板子要緊密地結(jié)合在一起,才能組成一個不漏水的木桶。

在常見的入侵案例中,大多數(shù)是利用Web應(yīng)用的漏洞,攻擊者先獲得一個低權(quán)限的webshell,然后通過低權(quán)限的webshell上傳更多的文件,并嘗試執(zhí)行更高權(quán)限的系統(tǒng)命令,嘗試在服務(wù)器上提升權(quán)限為root;接下來攻擊者再進(jìn)一步嘗試滲透內(nèi)網(wǎng),比如數(shù)據(jù)庫服務(wù)器所在的網(wǎng)段。

在這類入侵案例中,如果在攻擊過程中的任何一個環(huán)節(jié)設(shè)置有效的防御措施,都有可能導(dǎo)致入侵過程功虧一簣。但是世上沒有萬能靈藥,也沒有哪種解決方案能解決所有問題,因此非常有必要將風(fēng)險分散到系統(tǒng)的各個層面。就入侵的防御來說,我們需要考慮的可能有Web應(yīng)用安全、OS系統(tǒng)安全、數(shù)據(jù)庫安全、網(wǎng)絡(luò)環(huán)境安全等。在這些不同層面設(shè)計的安全方案,將共同組成整個防御體系,這也就是縱深防御的思想。

縱深防御的第二層含義,是要在正確的地方做正確的事情。如何理解呢?它要求我們深入理解威脅的本質(zhì),從而做出正確的應(yīng)對措施。

在XSS防御技術(shù)的發(fā)展過程中,曾經(jīng)出現(xiàn)過幾種不同的解決思路,直到最近幾年XSS的防御思路才逐漸成熟和統(tǒng)一。

XSS防御技術(shù)的發(fā)展過程

在一開始的方案中,主要是過濾一些特殊字符,比如:

<<笑傲江湖>> 會變成 笑傲江湖

尖括號被過濾掉了。

但是這種粗暴的做法常常會改變用戶原本想表達(dá)的意思,比如:

1<2 可能會變成 1 2

造成這種“烏龍”的結(jié)果就是因為沒有“在正確的地方做正確的事情”。對于XSS防御,對系統(tǒng)取得的用戶輸入進(jìn)行過濾其實是不太合適的,因為XSS真正產(chǎn)生危害的場景是在用戶的瀏覽器上,或者說服務(wù)器端輸出的HTML頁面,被注入了惡意代碼。只有在拼裝HTML時輸出,系統(tǒng)才能獲得HTML上下文的語義,才能判斷出是否存在誤殺等情況。所以“在正確的地方做正確的事情”,也是縱深防御的一種含義——必須把防御方案放到最合適的地方去解決。(XSS防御的更多細(xì)節(jié)請參考“跨站腳本攻擊”一章。)

近幾年安全廠商為了迎合市場的需要,推出了一種產(chǎn)品叫UTM,全稱是“統(tǒng)一威脅管理”(Unified Threat Management)。UTM幾乎集成了所有主流安全產(chǎn)品的功能,比如防火墻、VPN、反垃圾郵件、IDS、反病毒等。UTM的定位是當(dāng)中小企業(yè)沒有精力自己做安全方案時,可以在一定程度上提高安全門檻。但是UTM并不是萬能藥,很多問題并不應(yīng)該在網(wǎng)絡(luò)層、網(wǎng)關(guān)處解決,所以實際使用時效果未必好,它更多的是給用戶買個安心。

對于一個復(fù)雜的系統(tǒng)來說,縱深防御是構(gòu)建安全體系的必要選擇。

1.7.3 數(shù)據(jù)與代碼分離原則

另一個重要的安全原則是數(shù)據(jù)與代碼分離原則。這一原則廣泛適用于各種由于“注入”而引發(fā)安全問題的場景。

實際上,緩沖區(qū)溢出,也可以認(rèn)為是程序違背了這一原則的后果——程序在棧或者堆中,將用戶數(shù)據(jù)當(dāng)做代碼執(zhí)行,混淆了代碼與數(shù)據(jù)的邊界,從而導(dǎo)致安全問題的發(fā)生。

在Web安全中,由“注入”引起的問題比比皆是,如XSS、SQL Injection、CRLF Injection、X-Path Injection等。此類問題均可以根據(jù)“數(shù)據(jù)與代碼分離原則”設(shè)計出真正安全的解決方案,因為這個原則抓住了漏洞形成的本質(zhì)原因。

以XSS為例,它產(chǎn)生的原因是HTML Injection或JavaScript Injection,如果一個頁面的代碼如下:

    <html>
    <head>test</head>
    <body>
    $var
    </body>
    </html>

其中 $var是用戶能夠控制的變量,那么對于這段代碼來說:

    <html>
    <head>test</head>
    <body>

    </body>
    </html>

就是程序的代碼執(zhí)行段。

    $var

就是程序的用戶數(shù)據(jù)片段。

如果把用戶數(shù)據(jù)片段 $var當(dāng)成代碼片段來解釋、執(zhí)行,就會引發(fā)安全問題。

比如,當(dāng)$var的值是:

    <script  src=http://evil></script>

時,用戶數(shù)據(jù)就被注入到代碼片段中。解析這段腳本并執(zhí)行的過程,是由瀏覽器來完成的——瀏覽器將用戶數(shù)據(jù)里的<script>標(biāo)簽當(dāng)做代碼來解釋——這顯然不是程序開發(fā)者的本意。

根據(jù)數(shù)據(jù)與代碼分離原則,在這里應(yīng)該對用戶數(shù)據(jù)片段 $var進(jìn)行安全處理,可以使用過濾、編碼等手段,把可能造成代碼混淆的用戶數(shù)據(jù)清理掉,具體到這個案例中,就是針對 <、> 等符號做處理。

有的朋友可能會問了:我這里就是要執(zhí)行一個<script>標(biāo)簽,要彈出一段文字,比如:“你好!”,那怎么辦呢?

在這種情況下,數(shù)據(jù)與代碼的情況就發(fā)生了變化,根據(jù)數(shù)據(jù)與代碼分離原則,我們就應(yīng)該重寫代碼片段:

    <html>
    <head>test</head>
    <body>
    <script>
    alert("$var1");
    </script>
    </body>
    </html>

在這種情況下,<script>標(biāo)簽也變成了代碼片段的一部分,用戶數(shù)據(jù)只有 $var1能夠控制,從而杜絕了安全問題的發(fā)生。

1.7.4 不可預(yù)測性原則

前面介紹的幾條原則:Secure By Default,是時刻要牢記的總則;縱深防御,是要更全面、更正確地看待問題;數(shù)據(jù)與代碼分離,是從漏洞成因上看問題;接下來要講的“不可預(yù)測性”原則,則是從克服攻擊方法的角度看問題。

微軟的Windows系統(tǒng)用戶多年來深受緩沖區(qū)溢出之苦,因此微軟在Windows的新版本中增加了許多對抗緩沖區(qū)溢出等內(nèi)存攻擊的功能。微軟無法要求運行在系統(tǒng)中的軟件沒有漏洞,因此它采取的做法是讓漏洞的攻擊方法失效。比如,使用DEP來保證堆棧不可執(zhí)行,使用ASLR讓進(jìn)程的棧基址隨機(jī)變化,從而使攻擊程序無法準(zhǔn)確地猜測到內(nèi)存地址,大大提高了攻擊的門檻。經(jīng)過實踐檢驗,證明微軟的這個思路確實是有效的——即使無法修復(fù)code,但是如果能夠使得攻擊的方法無效,那么也可以算是成功的防御。

微軟使用的ASLR技術(shù),在較新版本的Linux內(nèi)核中也支持。在ASLR的控制下,一個程序每次啟動時,其進(jìn)程的棧基址都不相同,具有一定的隨機(jī)性,對于攻擊者來說,這就是“不可預(yù)測性”。

不可預(yù)測性(Unpredictable),能有效地對抗基于篡改、偽造的攻擊。我們看看如下場景:

假設(shè)一個內(nèi)容管理系統(tǒng)中的文章序號,是按照數(shù)字升序排列的,比如id=1000, id=1002, id=1003……

這樣的順序,使得攻擊者能夠很方便地遍歷出系統(tǒng)中的所有文章編號:找到一個整數(shù),依次遞增即可。如果攻擊者想要批量刪除這些文章,寫個簡單的腳本:

    for (i=0; i<100000; i++){
      Delete(url+"? id="+i);
    }

就可以很方便地達(dá)到目的。但是如果該內(nèi)容管理系統(tǒng)使用了“不可預(yù)測性”原則,將id的值變得不可預(yù)測,會產(chǎn)生什么結(jié)果呢?

id=asldfjaefsadlf, id=adsfalkennffxc, id=poerjfweknfd……

id的值變得完全不可預(yù)測了,攻擊者再想批量刪除文章,只能通過爬蟲把所有的頁面id全部抓取下來,再一一進(jìn)行分析,從而提高了攻擊的門檻。

不可預(yù)測性原則,可以巧妙地用在一些敏感數(shù)據(jù)上。比如在CSRF的防御技術(shù)中,通常會使用一個token來進(jìn)行有效防御。這個token能成功防御CSRF,就是因為攻擊者在實施CSRF攻擊的過程中,是無法提前預(yù)知這個token值的,因此要求token足夠復(fù)雜時,不能被攻擊者猜測到。(具體細(xì)節(jié)請參考“跨站點請求偽造”一章。)

不可預(yù)測性的實現(xiàn)往往需要用到加密算法、隨機(jī)數(shù)算法、哈希算法,好好使用這條原則,在設(shè)計安全方案時往往會事半功倍。

1.8 小結(jié)

本章歸納了筆者對于安全世界的認(rèn)識和思考,從互聯(lián)網(wǎng)安全的發(fā)展史說起,揭示了安全問題的本質(zhì),以及應(yīng)該如何展開安全工作,最后總結(jié)了設(shè)計安全方案的幾種思路和原則。在后續(xù)的章節(jié)中,將繼續(xù)揭示W(wǎng)eb安全的方方面面,并深入理解攻擊原理和正確的解決之道——我們會面對各種各樣的攻擊,解決方案為什么要這樣設(shè)計,為什么這最合適?這一切的出發(fā)點,都可以在本章中找到本質(zhì)的原因。

安全是一門樸素的學(xué)問,也是一種平衡的藝術(shù)。無論是傳統(tǒng)安全,還是互聯(lián)網(wǎng)安全,其內(nèi)在的原理都是一樣的。我們只需抓住安全問題的本質(zhì),之后無論遇到任何安全問題(不僅僅局限于Web安全或互聯(lián)網(wǎng)安全),都會無往而不利,因為我們已經(jīng)真正地懂得了如何用安全的眼光來看待這個世界!

(附)誰來為漏洞買單?http://hi.baidu.com/aullik5/blog/item/d4b8c81270601c3fdd54013e.html

昨天介紹了PHP中is_a()函數(shù)功能改變引發(fā)的問題http://hi.baidu.com/aullik5/blog/item/60d2b5fc2524c30a09244d0c.html,后來發(fā)現(xiàn)很多朋友不認(rèn)同這是一個漏洞,原因是通過良好的代碼習(xí)慣能夠避免該問題,比如寫一個安全的__autoload()函數(shù)。

我覺得我有必要講講一些安全方面的哲學(xué)問題,但這些想法只代表我個人的觀點,是我的安全世界觀。

互聯(lián)網(wǎng)本來是安全的,自從有了研究安全的人,就變得不安全了。

所有的程序本來也沒有漏洞,只有功能,但當(dāng)一些功能被用于破壞,造成損失時,也就成了漏洞。

我們定義一個功能是否是漏洞,只看后果,而不應(yīng)該看過程。

計算機(jī)用0和1定義了整個世界,但在整個世界中,并非所有事情都能簡單地用“是” 或者“非”來判斷,漏洞也是如此,因為破壞有程度輕重之分,當(dāng)破壞程度超過某一臨界值時,多數(shù)人(注意不是所有人)會接受這是一個漏洞的事實。但事物是變化的,這個臨界值也不是一成不變的,“多數(shù)人”也不是一成不變的,所以我們要用變化的觀點去看待變化的事物。

泄露用戶個人信息,比如電話、住址,在以前幾乎稱不上漏洞,因為沒有人利用;但在互聯(lián)網(wǎng)越來越關(guān)心用戶隱私的今天,這就變成了一個嚴(yán)重的問題,因為有無數(shù)的壞人時刻在想著利用這些信息搞破壞,非法攫取利益。所以,今天如果發(fā)現(xiàn)某網(wǎng)站能夠批量、未經(jīng)授權(quán)獲取到用戶個人信息,這就是一個漏洞。

再舉個例子。用戶登錄的memberID是否屬于機(jī)密信息?在以往做信息安全,我們都只知道“密碼”、“安全問題”等傳統(tǒng)意義上的機(jī)密信息需要保護(hù)。但是在今天,在網(wǎng)站的業(yè)務(wù)設(shè)計中,我們發(fā)現(xiàn)loginID也應(yīng)該屬于需要保護(hù)的信息。因為loginID一旦泄露后,可能會導(dǎo)致被暴力破解;甚至有的用戶將loginID當(dāng)成密碼的一部分,會被黑客猜中用戶的密碼或者是黑客通過攻擊一些第三方站點(比如SNS)后,找到同樣的loginID來嘗試登錄。

正因為攻擊技術(shù)在發(fā)展,所以我們對漏洞的定義也在不斷變化。可能很多朋友都沒有注意到,一個業(yè)務(wù)安全設(shè)計得好的網(wǎng)站,往往loginID和nickname(昵稱)是分開的。登錄ID是用戶的私有信息,只有用戶本人能夠看到;而nickname不能用于登錄,但可以公開給所有人看。這種設(shè)計的細(xì)節(jié),是網(wǎng)站積極防御的一種表現(xiàn)。

可能很多朋友仍然不愿意承認(rèn)這些問題是漏洞,那么什么是漏洞呢?在我看來,漏洞只是對破壞性功能的一個統(tǒng)稱而已。

但是“漏洞”這頂帽子太大,大到我們難以承受,所以我們不妨換一個角度看,看看是否“應(yīng)該修補(bǔ)”。語言真是很神奇的東西,很多時候換一個稱呼,就能讓人的認(rèn)可度提高很多。

在PHP的5.3.4版本中,修補(bǔ)了很多年來萬惡的0字節(jié)截斷功能http://www.phpweblog.net/GaRY/archive/2010/12/10/PHP_is_geliavable_now.html,這個功能被文件包含漏洞利用,釀造了無數(shù)“血案”。

我們知道PHP中include/require一個文件的功能,如果有良好的代碼規(guī)范,則是安全的,不會成為漏洞。

這是一個正常的PHP語言的功能,只是“某一群不明真相的小白程序員”在一個錯誤的時間、錯誤的地點寫出了錯誤的代碼,使得“某一小撮狡猾的黑客”發(fā)現(xiàn)了這些錯誤的代碼,從而導(dǎo)致漏洞。這是操作系統(tǒng)的問題,誰叫操作系統(tǒng)在遍歷文件路徑時會被0字節(jié)截斷,誰叫C語言的string操作是以0字節(jié)為結(jié)束符,誰叫程序員寫出這么小白的代碼,官方文檔里已經(jīng)提醒過了,關(guān)PHP什么事情,太冤枉了!

我也覺得PHP挺冤枉的,但C語言和操作系統(tǒng)也挺冤的,我們就是這么規(guī)定的,如之奈何?

但總得有人來為錯誤買單,誰買單呢?寫出不安全代碼的小白程序員?

No!學(xué)習(xí)過市場營銷方面知識的同學(xué)應(yīng)該知道,永遠(yuǎn)也別指望讓最終用戶來買單,就像老百姓不應(yīng)該為政府的錯誤買單一樣(當(dāng)然在某個神奇的國度除外)。所以必須得有人為這些不是漏洞,但造成了既成事實的錯誤負(fù)責(zé),我們需要有社會責(zé)任感的owner。

很高興的是,PHP官方在經(jīng)歷這么多年糾結(jié)、折磨、發(fā)瘋之后,終于勇敢地承擔(dān)起了這個責(zé)任(我相信這是一個很坎坷的心路歷程),為這場釀成無數(shù)慘案的鬧劇畫上了一個句號。但是我們?nèi)匀槐^地看到,cgi.fix_pathinfo的問題http://www.80sec.com/nginx-securit.html仍然沒有修改默認(rèn)配置,使用fastcgi的PHP應(yīng)用默認(rèn)處于風(fēng)險中。PHP官方仍然堅持認(rèn)為這是一個正常的功能,誰叫小白程序員不認(rèn)真學(xué)習(xí)官方文件精神!是啊,無數(shù)網(wǎng)站付出慘痛學(xué)費的正常功能!

PHP是當(dāng)下用戶最多的Web開發(fā)語言之一,但是因為種種歷史遺留原因(我認(rèn)為是歷史原因),導(dǎo)致在安全的“增值”服務(wù)上做得遠(yuǎn)遠(yuǎn)不夠(相對于一些新興的流行語言來說)。在PHP流行起來的時候,當(dāng)時的互聯(lián)網(wǎng)遠(yuǎn)遠(yuǎn)沒有現(xiàn)在復(fù)雜,也遠(yuǎn)遠(yuǎn)沒有現(xiàn)在這么多的安全問題,在當(dāng)時的歷史背景下,很多問題都不是“漏洞”,只是功能。

我們可以預(yù)見到,在未來互聯(lián)網(wǎng)發(fā)展的過程中,也必然會有更多、更古怪的攻擊方式出現(xiàn),也必然會讓更多的原本是“功能”的東西,變成漏洞。

最后,也許你已經(jīng)看出來了,我并不是要說服誰is_a()是一個漏洞,而是在思考,誰該為這些損失買單?我們未來遇到同樣的問題怎么辦?

對于白帽子來說,我們習(xí)慣于分解問題,同一個問題,我們可以在不同層面解決,可以通過良好的代碼規(guī)范去保證(事實上,所有的安全問題都能這么修復(fù),只是需要付出的成本過于巨大),但只有PHP在源頭修補(bǔ)了這個問題,才真正是善莫大焉。

BTW:is_a()函數(shù)的問題已經(jīng)申報了CVE,如果不出意外,security@php.net也會接受這個問題,所以它已經(jīng)是一個既成事實的漏洞了。

主站蜘蛛池模板: 新乡县| 家居| 郁南县| 永胜县| 和硕县| 佛山市| 长治县| 南京市| 通城县| 云阳县| 甘孜县| 咸阳市| 荥经县| 攀枝花市| 贵港市| 忻城县| 新宁县| 洞口县| 荥阳市| 巩留县| 泾阳县| 来凤县| 青龙| 德江县| 如皋市| 长顺县| 浠水县| 库伦旗| 兴宁市| 塘沽区| 广安市| 无锡市| 十堰市| 准格尔旗| 兰州市| 航空| 井冈山市| 昌都县| 闻喜县| 安徽省| 安康市|