亚洲日本免费-啊轻点灬太粗太长了三男一女-麻豆av电影在线观看-日韩一级片毛片|www.grbbt.com

如何阻止下一次心臟出血漏洞

  一、引言

  基于OpenSSL的心臟出血漏洞被認(rèn)為是CVE-2014-0160的嚴(yán)重問(wèn)題,OpenSSL被廣泛的應(yīng)用于SSL和TLS插件上。本文用對(duì)心臟出血漏洞的解釋來(lái)說(shuō)明這個(gè)漏洞是怎么被利用的。

  本文中研究了抗心臟出血漏洞及其相似漏洞的專用工具和技術(shù)。我首先通過(guò)簡(jiǎn)單的測(cè)試來(lái)分析為什么很多的工具和技術(shù)不能發(fā)現(xiàn)這些漏洞,這樣可以使我們更能了解到為什么之前的技術(shù)不能發(fā)現(xiàn)這些漏洞。我還要概括總結(jié)要點(diǎn)來(lái)減少這些的問(wèn)題。本文不介紹如何編寫(xiě)安全軟件,你可以從我的書(shū)《Secure Programming for Linux and Unix HOWTO》或是其他的著作中學(xué)習(xí)到這點(diǎn),本文中認(rèn)為您能開(kāi)發(fā)軟件。

  我的目的是為了幫助防止類(lèi)似漏洞的出現(xiàn),從而提高安全軟件的開(kāi)發(fā)能力。正如Orson Scott Card’s Ender’s Game中的虛幻人物Mazer Rackham所說(shuō)的“這里沒(méi)有老師,只有敵人…只有在敵人那里你才能了解到自己的弱點(diǎn)。”讓我們來(lái)了解這些漏洞,然后可以避免相似的漏洞再次出現(xiàn)。

  二、為什么這個(gè)漏洞不能更早的被發(fā)現(xiàn)?

  這個(gè)OpenSSL漏洞是由一個(gè)很熟悉的問(wèn)題引起的,這個(gè)關(guān)鍵的問(wèn)題就是緩沖區(qū)讀溢出,由于不正確的輸入導(dǎo)致。這些都是很常見(jiàn)的問(wèn)題,很多的工具是專門(mén)用來(lái)查找這方面的問(wèn)題,會(huì)使用很多工具對(duì)OpenSSL進(jìn)行定期檢查。

  Kupsch和Miller專門(mén)查找了心臟出血漏洞,在這個(gè)漏洞被發(fā)現(xiàn)之前,使用了很多的方法也沒(méi)有發(fā)現(xiàn)這個(gè)漏洞,雖然很多人和工具都用來(lái)查找類(lèi)似的漏洞。他們進(jìn)一步認(rèn)識(shí)到“心臟出血漏洞對(duì)當(dāng)前的輔助軟件提出了重大的挑戰(zhàn),而且我們不知道是否有工具能在這個(gè)漏洞被發(fā)現(xiàn)之前被使用。”我會(huì)強(qiáng)調(diào)一些其它的問(wèn)題和我自己的一些觀點(diǎn)。

  2.1 靜態(tài)分析

  在沒(méi)有執(zhí)行這個(gè)程序時(shí)的靜態(tài)分析。

  最常用來(lái)尋找漏洞的靜態(tài)分析工具是source code weakness analyzers,source code security analyzers, static application security testing,static analysis code scanners 和 code weakness analysis tools。每個(gè)源代碼分析工具是通過(guò)使用類(lèi)型匹配的方法來(lái)尋找漏洞的。有很多的報(bào)告可以評(píng)估這些工具。

  然而,在之前的時(shí)間里使用靜態(tài)分析工具沒(méi)有發(fā)現(xiàn)這個(gè)漏洞:

  1、Coverity:Coverity沒(méi)能在心臟出血漏洞公布之前發(fā)現(xiàn)這個(gè)漏洞。他們正在通過(guò)努力來(lái)提高他們的工具的質(zhì)量,從而在將來(lái)能夠發(fā)現(xiàn)相似的漏洞,使用了一些有趣的新啟發(fā)方法。

  2、HP/Fortify: HP/Fortify已經(jīng)公布了一些心臟出血漏洞的描述,但是我沒(méi)有任何的證明能說(shuō)明他們的靜態(tài)分析工具在漏洞公布前就發(fā)現(xiàn)了這個(gè)漏洞,在漏洞被公布后,他們確實(shí)是更改了他們的動(dòng)態(tài)測(cè)試軟件包,但是和之前的不同。在專門(mén)討論這個(gè)問(wèn)題時(shí),他們沒(méi)有證據(jù)讓我相信他們的工具真的在心臟出血漏洞被公布之前就發(fā)現(xiàn)了這個(gè)漏洞。

  3、Klocwork: Klocwork在正常的配置下沒(méi)有能夠偵測(cè)到這個(gè)漏洞。

  4、Grammatech: Grammatech 的CodeSonar同樣沒(méi)有偵測(cè)到這個(gè)漏洞。他們也是通過(guò)實(shí)驗(yàn)來(lái)提升能力,以便在以后能夠發(fā)現(xiàn)相似的漏洞。

  最主要的爭(zhēng)議就是這些工具都不能保證能夠發(fā)現(xiàn)所有的漏洞,甚至不能保證發(fā)現(xiàn)特定類(lèi)型的漏洞。很糟糕的是這些術(shù)語(yǔ)很混亂,所以我們首先要搞清這些術(shù)語(yǔ)的意思。

  本文中在分析軟件時(shí),使用的工具不能找到所有的漏洞,但是我找到了這個(gè)分析軟件的不足。在以前的文章中,很多人使用unsound來(lái)描述那些不能找到所有漏洞的來(lái)查找漏洞的工具。例如Bessey等人在分析Coverity的靜態(tài)分析工具,并且說(shuō):“像PREfix產(chǎn)品,我們也使用unsound。”我們的產(chǎn)品并沒(méi)有證明說(shuō)這是沒(méi)有錯(cuò)誤的,而是盡我們的能力來(lái)發(fā)現(xiàn)這些問(wèn)題。這項(xiàng)研究工作中存在很大的爭(zhēng)議,雖然它幾乎已經(jīng)成為商業(yè)軟件和研究項(xiàng)目的實(shí)際工具基礎(chǔ)。一個(gè)unsound術(shù)語(yǔ)會(huì)導(dǎo)致混亂,因?yàn)槿藗兪褂胮rogram checkers,它使用術(shù)語(yǔ)unsound來(lái)代替不同的意思。在一個(gè)博客上解釋了為什么相同術(shù)語(yǔ)會(huì)有兩種相互矛盾意思。“大多數(shù)的program checkers來(lái)證明定律的程序。特別情況下,主要的目的是在某個(gè)方面來(lái)證明程序的正確性。一個(gè)定律的證明是來(lái)證明這個(gè)定律的正確與否…人民在程序檢查過(guò)程中習(xí)慣了使用這種做法,所以他們沒(méi)有考慮bug的存在。但是一個(gè)bug的發(fā)現(xiàn)者不是要證明這個(gè)程序是不對(duì)的,而是用來(lái)證明有bug存在,使得他們報(bào)告了發(fā)現(xiàn)的bugs,它們就都變成了真正的bug,如果沒(méi)有錯(cuò)誤,將會(huì)忽略bug,因?yàn)樗麄儾荒茏C明是否正確。”

  本文中我使用了NIST SAMATE SATE V Ockham Sound Analysis標(biāo)準(zhǔn)來(lái)消除混亂,在NIST SAMATE用語(yǔ)中,工具是不能發(fā)現(xiàn)所有漏洞的,從而證明程序是不完備的。下面來(lái)說(shuō)明NIST是怎么區(qū)分程序的可靠性和完整性:“一個(gè)網(wǎng)站的代碼可能會(huì)出問(wèn)題,一個(gè)有bug的網(wǎng)站會(huì)有一系列問(wèn)題,這就是說(shuō)一些輸入會(huì)導(dǎo)致問(wèn)題。一個(gè)沒(méi)有bug的網(wǎng)站不會(huì)出現(xiàn)一些列問(wèn)題,就是說(shuō)它是安全的或是沒(méi)有漏洞的…這些可以從一個(gè)網(wǎng)站的報(bào)告中得知。或者說(shuō),一個(gè)網(wǎng)站有特殊的問(wèn)題或是一個(gè)網(wǎng)站沒(méi)有問(wèn)題…可靠就意味著每一個(gè)發(fā)現(xiàn)都是正確的。沒(méi)有必要使用工具產(chǎn)生每個(gè)網(wǎng)站的報(bào)告;這是完整的。”

  為什么那么多的源代碼分析工具是不完整的?首先,大多數(shù)的程序語(yǔ)言不是很容易能被分析的。其次,大多數(shù)的軟件使用靜態(tài)分析工具來(lái)分析也是很不簡(jiǎn)單的。最后,完整的分析工具要求更多的人來(lái)應(yīng)用在程序上。相反,不完整的分析工具能夠立刻應(yīng)用到程序上。他們成功的使用啟發(fā)的方法來(lái)鑒定漏洞和在有限的時(shí)間里來(lái)完善分析。但是,這里會(huì)有重要的警告:不完整的代碼分析工具常常會(huì)漏掉漏洞。

  心臟出血漏洞是一個(gè)鮮明的使用不完全的啟發(fā)方法不能發(fā)現(xiàn)的重要漏洞的例子,不能發(fā)現(xiàn)這個(gè)重要漏洞的最主要原因就是OpenSSL代碼很復(fù)雜;多個(gè)層次的間接尋址和超出了工具的分析能力,從而不能發(fā)現(xiàn)漏洞。局限性和深層次存在的原因是C, C++和Objective-C都很難使用靜態(tài)分析;像指針更難使用靜態(tài)管理。這并不是意味著靜態(tài)分析工具就是沒(méi)用的,靜態(tài)分析工具能夠測(cè)試軟件在大量的輸入后的表現(xiàn),工具的啟發(fā)原理會(huì)限制錯(cuò)誤報(bào)告的出現(xiàn)次數(shù)。但是更重要的是不完整的靜態(tài)分析工具使用了啟發(fā)原理后,在分析大的漏洞時(shí)會(huì)出現(xiàn)錯(cuò)誤。

  2.2 動(dòng)態(tài)分析

  動(dòng)態(tài)方法就是使用特定的輸入來(lái)運(yùn)行一個(gè)程序并試著發(fā)現(xiàn)漏洞。

  動(dòng)態(tài)分析局限性是它不能使用時(shí)間表來(lái)測(cè)試任何程序。如在一個(gè)瑣碎的程序中加入了64bit的整數(shù),會(huì)有2128種可能的輸入,測(cè)試這些輸入就要使用13.5十萬(wàn)億億年的時(shí)間。甚至大規(guī)模的并行計(jì)算也不能解決這個(gè)問(wèn)題。現(xiàn)實(shí)中的程序要比這復(fù)雜的多,因此動(dòng)態(tài)方法不能體現(xiàn)一個(gè)程序的安全性;他們只能顯示在測(cè)試中存在漏洞。

  但是這并是意味著動(dòng)態(tài)方法就是沒(méi)有用的。動(dòng)態(tài)方法在提升安全性上是很有用的,但是要了解到他們的局限。

  讓我們來(lái)分析我們廣泛使用的兩種方法,但是不能發(fā)現(xiàn)心臟出血漏洞: mostly-positive測(cè)試和fuzzers。

  2.2.1 mostly-positive自動(dòng)測(cè)試套件

  一個(gè)方法是開(kāi)發(fā)一個(gè)強(qiáng)大的自動(dòng)化測(cè)試套件。Eric S. Raymond和一些其他人在研究心臟出血漏洞時(shí),他的表述為:“我認(rèn)為很多人都認(rèn)為這個(gè)測(cè)試套件不能很好的工作…我以前學(xué)到了盡量去推進(jìn)傳統(tǒng)方法來(lái)完成你不能達(dá)到的程度。”我同意他的觀點(diǎn),一個(gè)好的自動(dòng)化測(cè)試套件是很強(qiáng)大的,特別是應(yīng)用于非安全性缺陷時(shí)。如果你沒(méi)有或是開(kāi)發(fā)一個(gè),就完全的停止,我們表示同意。

  但是,測(cè)試套件能否發(fā)現(xiàn)心臟出血漏洞要依靠你是怎么開(kāi)發(fā)的這個(gè)套件。很多的開(kāi)發(fā)人員都開(kāi)發(fā)了測(cè)試套件,這個(gè)套件主要是我說(shuō)的“mostly-positive”測(cè)試套件,它可能不能發(fā)現(xiàn)心臟出血漏洞。后面我將會(huì)討論negative測(cè)試,這種測(cè)試方法可能會(huì)有作用,但是我們要知道為什么一般的測(cè)試方法不能做到。

  很多的開(kāi)發(fā)者和組織者專門(mén)測(cè)試了正確的輸入時(shí)會(huì)發(fā)生什么。當(dāng)你這樣思考時(shí)就更有意義;一般的使用者都會(huì)抱怨在正確的輸入時(shí)是否會(huì)沒(méi)有正確的輸出,并且大多數(shù)的使用者不會(huì)測(cè)試在不正確的輸入時(shí)程序會(huì)有什么結(jié)果。如果你的目的是很快的分辨出問(wèn)題,在大多數(shù)的情況下,在正確的輸入時(shí)人們會(huì)努力控制能夠預(yù)測(cè)的錯(cuò)誤條件。很多的開(kāi)發(fā)人員不能思考到當(dāng)入侵者發(fā)送精心設(shè)計(jì)的輸入來(lái)利用程序時(shí)會(huì)發(fā)生什么。

  我會(huì)使用mostly-positive測(cè)試套件的方法來(lái)測(cè)試在正確的輸入時(shí)會(huì)發(fā)生什么。不幸運(yùn)的是,在很大程度上,今天的軟件入侵測(cè)試套件都是mostly-positive。都在關(guān)注開(kāi)發(fā)mostly-positive測(cè)試套件的測(cè)試。

  1、Test-driven development(TTD)是一個(gè)軟件開(kāi)發(fā)過(guò)程,“開(kāi)發(fā)者寫(xiě)了一個(gè)自動(dòng)測(cè)試工具來(lái)提升和增加新的功能,之后使用最少數(shù)量的代碼來(lái)通過(guò)測(cè)試,和最終生成新的代碼的接受標(biāo)準(zhǔn)。”通常情況下這些測(cè)試是用描述一個(gè)新功能要做什么,而不是他們不能做什么。

  2、當(dāng)很多的標(biāo)準(zhǔn)鏈接在一起,交互式測(cè)試就會(huì)決定他們是否能夠鏈接和分享數(shù)據(jù)。交互式測(cè)試能夠很好的幫助開(kāi)發(fā)者來(lái)提高一個(gè)協(xié)議標(biāo)準(zhǔn)。但是其他的實(shí)施方法也能遵守這個(gè)規(guī)則,其他的實(shí)施方法不能夠完成“什么不發(fā)生”的測(cè)試。

  mostly-positive測(cè)試實(shí)際上對(duì)于安全軟件來(lái)說(shuō)是沒(méi)有用的。mostly-positive測(cè)試一般不能測(cè)試正確的事物。對(duì)于心臟出血攻擊和其他的攻擊,攻擊者發(fā)送數(shù)據(jù)用不是平時(shí)用的格式。TTD和交互式測(cè)試都是好工具…但是你需要加強(qiáng)他們來(lái)改善安全軟件。

  代碼覆蓋工具對(duì)漏洞的發(fā)現(xiàn)沒(méi)有任何的幫助。一個(gè)開(kāi)發(fā)者可能會(huì)運(yùn)行代碼覆蓋工具來(lái)看下哪些程序沒(méi)有被測(cè)試,之后增加測(cè)試來(lái)達(dá)到大部分的代碼被測(cè)試。當(dāng)測(cè)試套件測(cè)試了80%-90%的代碼時(shí),很多人會(huì)很高興;一般很少會(huì)達(dá)到100%的覆蓋。測(cè)試覆蓋工具有某種安全價(jià)值,例如,他們有時(shí)能夠偵測(cè)到等待出發(fā)者的惡意軟件,他們也能夠核查是否有特別的程序能夠正確的運(yùn)行。但是使用典型的代碼覆蓋工具測(cè)試到100%的覆蓋,不能對(duì)抗心臟出血漏洞。心臟出血漏洞缺少恰當(dāng)?shù)妮斎腧?yàn)證。基本上,一個(gè)代碼覆蓋工具不能注意到丟失的代碼;只能注意到?jīng)]有測(cè)試的代碼。

  我要說(shuō)在OpenSSL里也不會(huì)有例外出現(xiàn),又如在蘋(píng)果的iOS設(shè)備上運(yùn)行SSL/TLS得到了錯(cuò)誤的結(jié)果時(shí),也能通過(guò)mostly-positive來(lái)證實(shí)它的測(cè)試。在這個(gè)漏洞中,SSL/TLS庫(kù)接受了有效的證明。然而,沒(méi)有人驗(yàn)證這個(gè)庫(kù)能拒絕某些無(wú)用的驗(yàn)證。如果你只是測(cè)試是否有效的數(shù)據(jù)會(huì)產(chǎn)生有效的結(jié)果,你就不能發(fā)現(xiàn)安全漏洞,因?yàn)榇蠖鄶?shù)的攻擊都是在基于程序沒(méi)有準(zhǔn)備好的時(shí)候輸入。

  如果你開(kāi)發(fā)的套件能使用我在下面描述的方法,你能夠通過(guò)一個(gè)好的測(cè)試套件來(lái)發(fā)現(xiàn)這個(gè)漏洞。首先,讓我們來(lái)研究fuzzing。

  2.2.2 Fuzzers 和fuzz測(cè)試

  Fuzz測(cè)試是一個(gè)隨機(jī)輸入,之后發(fā)送到程序測(cè)試去看是否出現(xiàn)不渴望的過(guò)程。進(jìn)行fuzz測(cè)試的軟件叫Fuzzers。

  Fuzz測(cè)試同傳統(tǒng)的測(cè)試不同,在傳統(tǒng)的測(cè)試過(guò)程中,你會(huì)有一個(gè)給定的輸入組,并且你知道每個(gè)輸入對(duì)應(yīng)的輸出情況。傳統(tǒng)測(cè)試會(huì)隨著測(cè)試數(shù)據(jù)的增加而變得更復(fù)雜,因?yàn)槟阋A(yù)測(cè)渴望的輸出結(jié)果。決定輸出想要的輸出結(jié)果是一個(gè)Oracle機(jī)制。使用一個(gè)Oracle的數(shù)據(jù)作為輸入的問(wèn)題被叫做Oracle problem。

  Fuzz測(cè)試處理不同的Oracle problem,因?yàn)樗皇窃谠噲D偵探能使程序崩潰的問(wèn)題。這就是使它在Fuzz測(cè)試中輸入更多的測(cè)試數(shù)據(jù),即使輸出測(cè)試更不準(zhǔn)確。Fuzzing測(cè)試方法是1988年Barton Miller在University of Wisconsin開(kāi)發(fā)的。在http://pages.cs.wisc.edu/~bart/fuzz/上有更多的有關(guān)fuzz測(cè)試的信息。

  Fuzzers經(jīng)常用來(lái)發(fā)現(xiàn)安全漏洞,因?yàn)樗麄兡軌驕y(cè)試大量不可想象的輸入。特別是,F(xiàn)uzzers常用來(lái)發(fā)現(xiàn)輸入驗(yàn)證的問(wèn)題,心臟出血漏洞就是在輸入驗(yàn)證錯(cuò)誤的基礎(chǔ)上產(chǎn)生的。但是典型的Fuzzers不能發(fā)現(xiàn)心臟出血漏洞,因?yàn)椋?/p>

  1、心臟出血漏洞是由于緩沖區(qū)讀入溢出,而不是緩沖區(qū)寫(xiě)入溢出的漏洞。大多數(shù)的Fuzzers只是發(fā)送大量的數(shù)據(jù)和尋找程序的崩潰。但是,當(dāng)緩沖區(qū)寫(xiě)入溢出常常會(huì)導(dǎo)致崩潰,緩沖區(qū)寫(xiě)入溢出在正常的環(huán)境里是不會(huì)崩潰的。在Fuzzing過(guò)程中,甚至?xí)褂靡恍?duì)策來(lái)解決寫(xiě)入溢出,而不是讀入溢出,如canary-based保護(hù)方法和非執(zhí)行堆棧。可靠性不是很大的問(wèn)題,因?yàn)榇嬖诜椒ㄊ浅鋈胍绯鰧?dǎo)致崩潰,或使用其他的測(cè)試工具來(lái)測(cè)試…這會(huì)給我們帶來(lái)第二個(gè)問(wèn)題。

  2、OpenSSL包括它的內(nèi)存分配路徑,并且除非使用特別的調(diào)試方法,不然我們會(huì)經(jīng)常使用他們。更糟糕的是這些特別的方法不能正常工作。特別是,OpenSSL使用它自身的應(yīng)用程序管理緩存來(lái)提高性能時(shí),而不是簡(jiǎn)單的依靠?jī)?nèi)存管理路徑。這種應(yīng)用程序管理緩存可以阻止許多典型的緩存例程,包括測(cè)試工具如electric fence、valgrind和address sanitizer。這就意味著使用fuzz測(cè)試來(lái)測(cè)試緩存的路徑問(wèn)題時(shí),測(cè)試會(huì)忽略一些特殊的情況。

  因?yàn)榧用芗夹g(shù)能在很大程度上減少fuzz測(cè)試的無(wú)效性,除非fuzzer有密碼和專門(mén)用來(lái)襲擊的密碼庫(kù)。有一些fuzzing不能在OpenSSL和一些密碼庫(kù)下嚴(yán)格執(zhí)行的推測(cè)應(yīng)該是正確的,然而,沒(méi)有什么能阻止密碼被fuzzers獲取。除此之外,心臟出血漏洞甚至在沒(méi)有密碼的情況下被發(fā)現(xiàn)。因此,就是在讀出溢出和OpenSSL使用自身的內(nèi)存緩存分配路徑的聯(lián)合使用時(shí),使fuzzing變的無(wú)效。

  三、用什么來(lái)對(duì)抗類(lèi)似心臟出血的漏洞?

  這里有部分在先前可以對(duì)抗心臟出血漏洞的軟件和工具,我會(huì)特別的介紹一些好用并且免費(fèi)的自由開(kāi)源、源代碼軟件。

  首先是一些說(shuō)明:

  不要只用一種工具或一種技術(shù)來(lái)開(kāi)發(fā)安全軟件。開(kāi)發(fā)安全軟件要集合很多的方法,最開(kāi)始要知道怎么開(kāi)發(fā)安全軟件。大多數(shù)的組織最初是使用簡(jiǎn)潔清晰的方法來(lái)開(kāi)發(fā)安全軟件,啟用和注意編輯器的警告標(biāo)志,使用源代碼弱點(diǎn)分析工具,讓多人進(jìn)行研究,運(yùn)行fuzzers,使用大量的自動(dòng)入侵工具套件。如果你只是使用一種技術(shù),你只能對(duì)抗上一次攻擊而不是這次。例如,會(huì)大量的忽略掉警告標(biāo)志,即使是警告標(biāo)志不能發(fā)現(xiàn)心臟出血。那就是說(shuō),當(dāng)攻擊成功時(shí),最重要的是怎么完善軟件,攻擊者可能如使用一樣的方法來(lái)入侵軟件。更好的改進(jìn)也能對(duì)抗其他的攻擊。

  這不存在一種類(lèi)型的工具和技術(shù)的列表,不同的工具有不同的用途。可以在[BAH2009] [NIST]上了解更多關(guān)于各個(gè)類(lèi)型的工具和技術(shù)。我創(chuàng)建了這個(gè)特別的列表,但是我要盡量清楚我的意思。

  先前沒(méi)有一個(gè)明確和完整的用來(lái)發(fā)現(xiàn)心臟出血漏洞的工具和技術(shù)的列表,我很想做一個(gè),我希望得到更好的建議。

  以上是一些說(shuō)明,先前是什么在對(duì)抗這個(gè)漏洞的,為了完成這個(gè),我已經(jīng)大致的完成了這個(gè)列表,用最簡(jiǎn)單的方式介紹他們。這是最粗略的,會(huì)有一些問(wèn)題;歡迎來(lái)改進(jìn)。使用更多的方法來(lái)對(duì)抗其他類(lèi)似漏洞,不只是心臟出血。使用動(dòng)態(tài)和靜態(tài)分析法來(lái)識(shí)別在括號(hào)里的副標(biāo)題。

  3.1 使用negative測(cè)試(動(dòng)態(tài)分析)

  negative測(cè)試會(huì)得到錯(cuò)誤的結(jié)果。例如,對(duì)于一個(gè)設(shè)置了密碼的系統(tǒng)來(lái)說(shuō),在知道有效的用戶名和密碼時(shí),要通過(guò)很多次的回歸測(cè)試才能登錄成果。negative測(cè)試會(huì)顯示很多無(wú)用的用戶名和密碼,其他的無(wú)效的輸入會(huì)阻止用戶登錄。

  通過(guò)negative測(cè)試方法創(chuàng)建了一系列的使用錯(cuò)誤輸入的測(cè)試。我指的是每個(gè)類(lèi)型的輸入,因?yàn)椴荒軠y(cè)試每一個(gè)輸入,在動(dòng)態(tài)測(cè)試中能得到解釋。在回歸測(cè)試工件中要包含無(wú)效數(shù)值來(lái)測(cè)試每一個(gè)輸入,每個(gè)狀態(tài)/協(xié)議轉(zhuǎn)換,每個(gè)使用說(shuō)明書(shū)等等。這就會(huì)立刻發(fā)現(xiàn)心臟出血漏洞,因?yàn)樾呐K出血漏洞包含一個(gè)不正確數(shù)據(jù)的長(zhǎng)數(shù)值。這也會(huì)發(fā)現(xiàn)其他類(lèi)似CVE-2014-1266的錯(cuò)誤,如在蘋(píng)果iOS上使用SSL/TLS會(huì)得到的錯(cuò)誤。在CVE-2014-1266中,iOS存在接受無(wú)效認(rèn)證的問(wèn)題。很多的測(cè)試中存在有效的認(rèn)證…但是,沒(méi)有足夠的測(cè)試來(lái)測(cè)試無(wú)效的認(rèn)證。

  在大多數(shù)情況下只有negative測(cè)試對(duì)安全還有點(diǎn)用途,之前,我注意到重要的是如何創(chuàng)建測(cè)試套件。對(duì)于閱讀本文來(lái)說(shuō)是明顯的,特別是,當(dāng)我懷疑Eric S. Raymond在討論測(cè)試的優(yōu)勢(shì)時(shí)使用這些類(lèi)型的測(cè)試。但是這對(duì)于軟件的開(kāi)發(fā)者來(lái)說(shuō)是明顯的,大多數(shù)的開(kāi)發(fā)者和組織者都是在使用mostly-positive test套件。很多的開(kāi)發(fā)者很難像攻擊者一樣的思考,只是錯(cuò)誤的通過(guò)廣泛的測(cè)試不可能發(fā)現(xiàn)的原因。

  通過(guò)negative測(cè)試的就是起初的半自動(dòng)的過(guò)程,您可以開(kāi)發(fā)出可以執(zhí)行計(jì)算機(jī)可處理的規(guī)范,并生成大量測(cè)試結(jié)果的工具…之后看看是否可以控制它。

  另一個(gè)使用negative測(cè)試的重要條件就是是否有一個(gè)標(biāo)準(zhǔn),可能合作開(kāi)發(fā)一個(gè)獨(dú)立的普通測(cè)試工件作為FLOSS項(xiàng)目。之后可以通過(guò)快速測(cè)試所有當(dāng)前和以后要執(zhí)行的方法,并且阻止使用者遇到問(wèn)題。我強(qiáng)烈的推薦使用SSL/TLS協(xié)議開(kāi)發(fā)一般目的測(cè)試工件;不然會(huì)減少效果,這會(huì)增加應(yīng)用的安全性。單獨(dú)的應(yīng)用也需要使用附加測(cè)試來(lái)補(bǔ)充單一測(cè)試,但是一般的大測(cè)試套件是很有用的。

  軟件測(cè)試是一個(gè)完整的領(lǐng)域。存在著不同類(lèi)型的測(cè)試方法和測(cè)試范圍標(biāo)準(zhǔn)。我只能在本文中總結(jié)測(cè)試。更一般的信息可以看下Paul Ammann and Jeff Offutt 的Introduction to Software Testing。但是要理解這個(gè):只用使用有效的輸入來(lái)測(cè)試來(lái)發(fā)現(xiàn)這多的問(wèn)題,如心臟出血漏洞。

  我不知道在整個(gè)negative測(cè)試中依靠什么,或是其他什么單獨(dú)的技術(shù),對(duì)于安全來(lái)說(shuō)。動(dòng)態(tài)的方法很自然,在真實(shí)輸入空間只能測(cè)試一個(gè)微不足道的部分。但是這種方法很容易發(fā)現(xiàn)安全漏洞。

  3.2 地址核對(duì)和標(biāo)準(zhǔn)內(nèi)存分配在fuzzing

  不幸運(yùn)的是一般的fuzz測(cè)試方法在這種情況下是不能很好使用,但是我們可以學(xué)習(xí)簡(jiǎn)單的過(guò)程。如果可以使fuzzing對(duì)一系列的地址進(jìn)行有效果的、容易的核對(duì)和使用。這種類(lèi)型的工具能偵測(cè)到在執(zhí)行過(guò)程中讀溢出和加寫(xiě)溢出,并且常常發(fā)現(xiàn)其他的存儲(chǔ)問(wèn)題。

  許多的工具能夠完成對(duì)地址的核對(duì);每一種工具都有兩面性。但是,如果你沒(méi)有使用其他的什么工具,我強(qiáng)烈的建議你嘗試下address sanitizer。

  address sanitizer簡(jiǎn)單有效;它只是一個(gè)在LLVM/clang和gcc中建立的附加的標(biāo)志。address sanitizer沒(méi)有什么神奇的;它只是擅長(zhǎng)偵測(cè)緩沖區(qū)的讀寫(xiě)溢出問(wèn)題,釋放后使用或是雙重釋放。它也能偵測(cè)到use-after-return和存儲(chǔ)泄漏。它不能發(fā)現(xiàn)所有的存儲(chǔ)問(wèn)題,但是這是一個(gè)很好的工具。它的表現(xiàn)超出平均的73%,使用2x-4x的存儲(chǔ)。這種表現(xiàn)一般和測(cè)試環(huán)境是無(wú)關(guān),在偵測(cè)這些問(wèn)題時(shí)它很少被提到,在測(cè)試過(guò)程中Chromium和Firefox網(wǎng)頁(yè)瀏覽器都使用的address sanitizer。要了解更多可以去看USENIX 2012或是address sanitizer網(wǎng)頁(yè)。

  還有其他的工具能夠偵測(cè)內(nèi)存的使用和分配地址的問(wèn)題。很多人使用guard pages來(lái)檢測(cè)讀和寫(xiě)在緩存。Valgrind被廣泛使用和廣受歡迎;valgrind在檢測(cè)內(nèi)存時(shí)能發(fā)現(xiàn)很多的問(wèn)題包括在堆棧中讀溢出。另一個(gè)廣泛使用的工具是electric fence。在運(yùn)行不同的fuzzer時(shí)可以使用不同的工具。

  一般情況下,使用fuzz測(cè)試時(shí)你必須打開(kāi)你能打開(kāi)的所有的探測(cè)設(shè)備。第一個(gè)fuzzer偵測(cè)時(shí)使用這種機(jī)制“沒(méi)有改變的程序崩潰或是死掉?”并且很多的fuzzer還只能做這個(gè)。你必須要加強(qiáng)程序的訪問(wèn),并且要開(kāi)發(fā)盡可能多的訪問(wèn)。你可以增加額外的核對(duì)來(lái)確保中間和最終程序語(yǔ)句的正確。要不是心臟出血漏洞的出現(xiàn),你至少應(yīng)該打開(kāi)無(wú)效的內(nèi)存訪問(wèn)探測(cè)器,如address sanitizer。

  許多的工具包括address sanitizer和基于程序的guard page,要求這些程序具有測(cè)試正常分配和釋放內(nèi)存的能力。特別是,程序沒(méi)有必要使用符合分派準(zhǔn)測(cè)的機(jī)制。至少,這個(gè)程序應(yīng)該可以輕松地使用正常分配方法用于fuzz測(cè)試。

  一個(gè)相對(duì)的方法是concolic測(cè)試,CREST就是一個(gè)基于C的concolic測(cè)試的自動(dòng)測(cè)試過(guò)程工具。但是CREST目前只能用于象征性為線性整數(shù)的運(yùn)算,所以它能在這種情況下工作。更一般的是現(xiàn)在的concolic測(cè)試工具不可能發(fā)現(xiàn)心臟出血漏洞。如果哪個(gè)人說(shuō)他確認(rèn)concolic測(cè)試發(fā)現(xiàn)了心臟出血漏洞,請(qǐng)讓我知道。

  大家一直都在為fuzzers是否比negative測(cè)試復(fù)雜而爭(zhēng)論不休,但是這只是我的推理。negative測(cè)試的一個(gè)優(yōu)點(diǎn)是它很容易入手;假設(shè)你已經(jīng)有了一個(gè)測(cè)試套件,你就可以開(kāi)始negative測(cè)試。更重要的是negative測(cè)試能快速給出一個(gè)模糊導(dǎo)致問(wèn)題的答案,他們要求計(jì)算能力很少的開(kāi)發(fā)者使用每一種方法來(lái)獲得重復(fù)測(cè)試套件。相反,fuzz測(cè)試要求更好的計(jì)算能力和對(duì)結(jié)果的解釋;計(jì)算能力不算什么,這會(huì)影響到對(duì)開(kāi)發(fā)者的反饋速度。一個(gè)潛在的更快negative測(cè)試的反饋能夠是開(kāi)發(fā)者更快的實(shí)現(xiàn)檢測(cè)和修復(fù);今天最大的問(wèn)題就是開(kāi)發(fā)者的時(shí)間,而不是計(jì)算時(shí)間;一個(gè)最好的機(jī)制能減少開(kāi)發(fā)過(guò)程的復(fù)雜度。你也可以在某個(gè)特定的協(xié)議下,使用negative測(cè)試套件;你能夠在每個(gè)測(cè)試設(shè)備和實(shí)施方法中輕松的重新使用測(cè)試套件。當(dāng)然,這不存在什么沖突;最好使用fuzz測(cè)試和negative測(cè)試兩種方法。

  3.3 編輯內(nèi)存分配標(biāo)準(zhǔn)和使用address guard或是sanitizer

  如果在對(duì)抗來(lái)自潛在的漏洞攻擊,在未知的環(huán)境里你現(xiàn)在就要使用一個(gè)程序怎么辦呢?

  一個(gè)方法就是使用偵測(cè)在分配的內(nèi)存的最后區(qū)域來(lái)實(shí)現(xiàn)讀的機(jī)制,但是使用這種方法你不能改變測(cè)試怎么運(yùn)行;這個(gè)觀點(diǎn)就是你實(shí)際上用的在一個(gè)分配要求下的多重分配機(jī)制。

  存在運(yùn)行時(shí)間偵測(cè)漏洞的多種機(jī)制;這就是一些例子:

  1、Address sanitizer。你要重復(fù)調(diào)試一個(gè)程序時(shí)可以使用它。在LLVM/clang和gcc編輯器上Address sanitizer就是一個(gè)標(biāo)志,這相對(duì)與C程序的軟件簡(jiǎn)單的多,這占了平均運(yùn)行的73%,和2x-4x的存儲(chǔ)。這不是你想只能手機(jī)上做的,很多繁忙的網(wǎng)站不歡迎這些。現(xiàn)在的計(jì)算機(jī)比過(guò)去的有更好的能力和存儲(chǔ),一些環(huán)境中就會(huì)被接受…這就是你能夠立刻對(duì)抗未知攻擊的可能性。Address sanitizer在偵測(cè)一長(zhǎng)系列潛在問(wèn)題上很有作用,包括大量無(wú)效的緩沖區(qū)訪問(wèn)。Address sanitize不是在所有的編輯器里都無(wú)效;這要在其他的如C, C++, 和Objective-C編輯器中來(lái)添加它。

  2、Intel Memory Protection Extensions。MPX新增了叫邊界寄存器的寄存器來(lái)控制指針的邊界,使用新的指令來(lái)運(yùn)行和使用邊界。MPX使用Skylake架構(gòu),但是在2014年這些CPU不能和公眾見(jiàn)面。這要更長(zhǎng)的時(shí)間被廣泛的得到使用,那不能組成non-Intel系統(tǒng)。

  3、內(nèi)存分配保護(hù)頁(yè)面。一些系統(tǒng)內(nèi)存分配能夠在分配一個(gè)用來(lái)組織讀和寫(xiě)的內(nèi)存后,添加一個(gè)未定的保護(hù)頁(yè)面。這些能否會(huì)禁止和阻止心臟出血漏洞,這些取決于它是如何實(shí)施的。OpenBSD的malloc的實(shí)施支持保護(hù)界面。在OpenBSD中,G選項(xiàng)會(huì)導(dǎo)致“使用保護(hù)頁(yè)面后的每個(gè)頁(yè)面分配到的數(shù)據(jù)大小過(guò)大,這些會(huì)導(dǎo)致訪問(wèn)錯(cuò)誤。”這會(huì)與P選項(xiàng)進(jìn)行組合來(lái)移動(dòng)一個(gè)頁(yè)面內(nèi)的分配。OpenBSD機(jī)制可以啟動(dòng)特定的程序,甚至是特定的默認(rèn)情況下,在整個(gè)系統(tǒng)中啟動(dòng),這樣就可以在更多的環(huán)境下得到保護(hù)。OpenBSD的malloc機(jī)制有一個(gè)弱點(diǎn):即使開(kāi)啟G和P兩個(gè)啟動(dòng)項(xiàng),少量的分配不會(huì)立刻完成保護(hù)頁(yè)面。如果OpenBSD的保護(hù)界面機(jī)制能夠在較少量的分配后立刻插入一個(gè)保護(hù)頁(yè)面,我認(rèn)為會(huì)更好,即使這可能會(huì)對(duì)速度和內(nèi)存大小有很大的影響。但是即使是這樣,開(kāi)啟G和P就意味著所有大于半頁(yè)的分配會(huì)立刻跟隨一個(gè)保護(hù)頁(yè)面,并且分配一個(gè)半頁(yè)或是更少將會(huì)泄漏半頁(yè)。這就會(huì)明顯的減少泄漏規(guī)模,相比于原來(lái)心臟出血漏洞攻擊時(shí)泄露的64K。內(nèi)存分配必須要對(duì)齊,所以保護(hù)頁(yè)面可能泄漏一些字節(jié)的信息,這就取決于如何實(shí)施的。我懷疑Address sanitizer要比增加保護(hù)頁(yè)面的分配快,但是添加保護(hù)頁(yè)面不要求更多的程序來(lái)進(jìn)行重新編譯,這就是它的優(yōu)勢(shì)。不幸運(yùn)的是GUN的libc中malloc不能有附加的這些功能。

  當(dāng)然,這種方法假設(shè)你有一個(gè)能啟動(dòng)(1)的內(nèi)存保護(hù)機(jī)制和(2)內(nèi)存保護(hù)機(jī)制也會(huì)在這種機(jī)制下工作。很多的機(jī)制可以對(duì)抗緩存寫(xiě)溢出,不是緩存讀溢出,心臟出血漏洞就利用了讀溢出。例如:GUN的libc中的malloc()可以選擇MALLOC_CHECK_。這就是防止寫(xiě)溢出的方法,但是我不認(rèn)為它能對(duì)抗類(lèi)似心臟出血的讀溢出。同樣,Dmalloc’s fence-post檢測(cè)“在程序從這個(gè)區(qū)域中讀取時(shí)不能注意到,只有在寫(xiě)入時(shí)才會(huì)有通知。”我覺(jué)得GUN的libc和一些類(lèi)似的運(yùn)行過(guò)程中也要增加類(lèi)似OpenBSD的malloc的保護(hù)頁(yè)面機(jī)制,從而對(duì)抗讀溢出。

  這是一個(gè)可以減少傷害的方法,而不是一個(gè)消除個(gè)問(wèn)題的辦法。從安全的角度來(lái)看這種方法把缺少保密變成了缺少實(shí)用。然而在很多的情況下這是一個(gè)很好的協(xié)議。一旦受到攻擊,這個(gè)方法就會(huì)使問(wèn)題變成可視化的,一旦問(wèn)題可視化后就變的很好改正了。

  這個(gè)方法很容易和honeypot或honeynet聯(lián)系在一起。在honeypot或honeynet系統(tǒng)上設(shè)置這些硬化的方法。如果攻擊者試圖破壞軟件,這個(gè)軟件不會(huì)崩潰,并且會(huì)記錄下攻擊者的重要日志和追蹤記錄。Forensics就會(huì)偵測(cè)到一些專門(mén)利用一日0攻擊。我認(rèn)為通過(guò)一些日志記錄結(jié)合入侵偵測(cè)系統(tǒng)來(lái)進(jìn)行追蹤;在硬化密碼庫(kù)中發(fā)生了崩潰,就會(huì)特意的記錄下。這就會(huì)使普遍的偵測(cè)利用一日0攻擊更加的容易。分布核心基礎(chǔ)設(shè)施組織和在互聯(lián)網(wǎng)上其他組織都可以建立這些類(lèi)保護(hù)我們。

  雖然這種方法并不能完全解決這個(gè)問(wèn)題,但是他能提供一個(gè)有力的緩解功能。一些發(fā)行者或組織可能需要在特定情況下使用這些措施,或至少使這些措施變得更容易。

  修改代碼不會(huì)很復(fù)雜,并且重新編譯也是很簡(jiǎn)單的。不過(guò),在很多的設(shè)備上性能的欠佳都體現(xiàn)的很顯著,可能是你失去了硬件后的性能。特別是在使用Address sanitizer時(shí),你會(huì)失去一半的速度。因此,我指望使用這種復(fù)雜的解決方法,就要考慮到硬件的消耗。在很多的情況下,會(huì)影響到運(yùn)行,在智能手機(jī)上就會(huì)降低運(yùn)行速度和電池的壽命,對(duì)于當(dāng)前流行的服務(wù)器的話,也會(huì)減慢反應(yīng)速度和增加電量的消耗。如果將來(lái)的CPU能支持Address sanitizer,對(duì)速度的影響就會(huì)顯著的降低了。我希望CPU制造商能考慮下這點(diǎn)。

  3.4 關(guān)注各個(gè)領(lǐng)域的手動(dòng)檢測(cè)驗(yàn)證

  漏洞的代碼是人為審查的,顯然只有一個(gè)人來(lái)審查是不行的。

  然而,大量的工作就要有專門(mén)的人來(lái)檢查每個(gè)領(lǐng)域,為確保得到有效的驗(yàn)證,有時(shí)會(huì)在計(jì)算機(jī)安全中得到一個(gè)不好的名字。我懷疑的原因之一就是有時(shí)候,那些部署清單的人在做什么,之后也不能很好的利用它。但是出色的飛行員經(jīng)常使用儀表盤(pán),他們知道是做什么的。如果補(bǔ)丁是他們使用清單上工具后的唯一成果,“必須證明每一個(gè)不可信的數(shù)據(jù)字段進(jìn)行驗(yàn)證,”之后這個(gè)漏洞被反擊。

  列入人為檢查/審計(jì)的一部分,和一些簡(jiǎn)單的方法不同。然而,這確實(shí)要就檢測(cè)人能了解所有的補(bǔ)丁,它不能依靠以前的代碼來(lái)得到幫助。

  3.5 對(duì)文件包括注解系統(tǒng)的配置源代碼的弱點(diǎn)分析

  傳統(tǒng)的源代碼弱點(diǎn)分析是找不到心臟出血漏洞,因?yàn)樗麄兪褂玫氖峭ㄓ玫膯l(fā)式方法,代碼復(fù)雜,在這種情況下不能很好的起到作用。它總是你能看到的最簡(jiǎn)潔的代碼,但是基于你要完成的任務(wù)總是會(huì)有一些復(fù)雜性,真實(shí)情況下人類(lèi)是不能達(dá)到完美的簡(jiǎn)約。Coverity公司正在開(kāi)發(fā)一些新的,他們認(rèn)為能夠檢測(cè)到心臟出血漏洞的啟發(fā)方法…并且對(duì)他們是有好處的。至少有一個(gè)人已經(jīng)使用了類(lèi)似的啟發(fā)方式。事實(shí)上,我希望所有的代碼分析工具都能得到改善,從而發(fā)現(xiàn)他們以前不能發(fā)現(xiàn)的漏洞。但通用的啟發(fā)方式在某個(gè)特定的時(shí)間點(diǎn)只能達(dá)到這個(gè)程度,你能做的更好嗎?

  回答是肯定的,它叫做為上下文配置的源代碼弱點(diǎn)分析工具。基本思想是,你開(kāi)始使用一個(gè)惡源代碼弱點(diǎn)分析工具,之后你在提供更多的你要分析的程序的信息。這種方法比僅僅運(yùn)行源代碼弱點(diǎn)分析工具需要更多的時(shí)間,而這些額外的信息通常要和一個(gè)特定的工具聯(lián)系在一起。然而,提供你需要的程序的信息,源代碼弱點(diǎn)分析工具可以能更好的工作。

  Klocwork已經(jīng)表示這種方法對(duì)心臟出血漏洞是很有效的。

  現(xiàn)在讓我們來(lái)談?wù)勛⑨屜到y(tǒng)。在很多的地方來(lái)為靜態(tài)分析工具提供這種額外的信息。一個(gè)常用的方法就是對(duì)程序添加額外的注釋機(jī)制,在修改程序時(shí)會(huì)使用他們。這些注解可能在更改的代碼中進(jìn)行添加,添加在注釋中,或是加在單獨(dú)的文件里。使用C的工具或是注解包括Microsoft’s SAL、splint、Deputy、Oink/CQual++、cqual、和Frama-C ANSI/ISO C。你可以很容易得出添加這些信息確實(shí)是一個(gè)不同的技術(shù)。

  認(rèn)真的使用這些額外的注解來(lái)對(duì)抗漏洞就要有很大的工作量,如果從現(xiàn)存的代碼來(lái)說(shuō)。對(duì)于C來(lái)說(shuō)存在許多不同的不兼容的注釋系統(tǒng)。對(duì)于他們來(lái)說(shuō)是沒(méi)有什么標(biāo)準(zhǔn)的,這會(huì)進(jìn)一步的阻礙他們的使用。畢竟,它需要添加注釋和這些注釋會(huì)把你鎖到一個(gè)特定的工具中;Microsoft SAL會(huì)有更多的問(wèn)題,沒(méi)有FLOSS的應(yīng)用和這只能在Windows上使用。我認(rèn)為如果針對(duì)每個(gè)主要的編程語(yǔ)言包括C在內(nèi),任何一種單一被廣泛接受的標(biāo)準(zhǔn)注釋符號(hào),注釋系統(tǒng)將會(huì)更加廣泛的應(yīng)用。當(dāng)沒(méi)有這么個(gè)符號(hào)時(shí),像C語(yǔ)言等語(yǔ)言就會(huì)很難得到那樣一個(gè)協(xié)議。Peter Gutmann已經(jīng)寫(xiě)了一些他的經(jīng)歷。

  但是,注解系統(tǒng)是由一些好處的,注解系統(tǒng)能夠發(fā)現(xiàn)簡(jiǎn)單的漏洞,不用在轉(zhuǎn)變成不同的語(yǔ)言。他們也很少去轉(zhuǎn)變成不同的語(yǔ)言,當(dāng)然,這并不沖突;你可以切換語(yǔ)言,使用一種新的語(yǔ)言在注釋系統(tǒng)中。

  3.6 實(shí)現(xiàn)100%的分支覆蓋率

  或許有另一種方法可以發(fā)現(xiàn)心臟出血漏洞,實(shí)現(xiàn)100%的分支覆蓋率。如前面所述,在一個(gè)缺失特定程序的中輸入有效的驗(yàn)證碼時(shí),分支測(cè)試是不檢測(cè)到的。但是分支覆蓋可以在不同的實(shí)現(xiàn)方法中檢測(cè)未經(jīng)驗(yàn)證的分支程序。努力實(shí)現(xiàn)一個(gè)測(cè)試套件,讓多個(gè)實(shí)現(xiàn)全覆蓋分支大大增加了丟失了驗(yàn)證碼和遺漏了異常處理時(shí)被檢測(cè)到的可能性。更強(qiáng)的測(cè)試覆蓋措施也會(huì)工作的很好,如修改條件/判定語(yǔ)句。

  這個(gè)測(cè)試套件必須要包含多個(gè)應(yīng)用,實(shí)現(xiàn)100%的分支覆蓋。更重要的是,有不同的實(shí)現(xiàn)方式,效果更好。最終,用一個(gè)特別的方法來(lái)發(fā)現(xiàn)漏洞。此外,這種方法比其他的方法更難發(fā)現(xiàn)安全漏洞。可能是因?yàn)樵谙嗤穆窂较螺斎氩煌臄?shù)值,但是只有小部分可以引起問(wèn)題。如果在測(cè)試中其他的一種方法實(shí)施了特定的組件和實(shí)現(xiàn)了潛在的缺失驗(yàn)證碼的代碼,它也只能有作用。我從來(lái)沒(méi)有在其他的文獻(xiàn)中見(jiàn)過(guò)這個(gè)特定的方法;人們通常討論一個(gè)執(zhí)行分支的覆蓋。不過(guò),會(huì)注意到這種方法不僅可以提高能力,也能發(fā)現(xiàn)特殊的漏洞。

  實(shí)現(xiàn)100%的分支覆蓋率比徹底的negative測(cè)試更加復(fù)雜,這是因?yàn)槿绻阌袀€(gè)很差的測(cè)試套件,它會(huì)花費(fèi)大量的時(shí)間來(lái)從一個(gè)錯(cuò)誤的分支轉(zhuǎn)向,來(lái)弄清楚怎么激發(fā)它。錯(cuò)過(guò)的分支往往是很難觸發(fā)的在特定錯(cuò)誤的處理系統(tǒng)中,或是對(duì)無(wú)法驗(yàn)證“不會(huì)發(fā)生”的分支作防御性設(shè)計(jì)。此外,這個(gè)套件變得更強(qiáng)大能夠?qū)崿F(xiàn)100%的覆蓋;很多的組織不能?chē)L試增加一個(gè)單一的方法來(lái)使分支覆蓋到100%,不關(guān)心100%的分支覆蓋。

  這就存在一個(gè)問(wèn)題:這不能很好的反擊心臟出血漏洞,因?yàn)樵诤艽蟪潭壬先Q于所有的配置擴(kuò)展或是注解以及怎么使用。在另一方面,它們不取決于完全沖擊的正確輸入;靜態(tài)分析工具可以同時(shí)檢測(cè)大量的問(wèn)題。

  3.7 攻擊運(yùn)行認(rèn)定

  軟件開(kāi)發(fā)人員積極的插入和開(kāi)啟運(yùn)行認(rèn)定。有人猜測(cè)這是對(duì)心臟出血的反擊,所以我將在這里研究下這中可能性。

  軟件開(kāi)發(fā)人員可以斷言各種價(jià)值關(guān)系和狀態(tài)必須是正確的。這些斷言可以在運(yùn)行時(shí)停留。幾乎所有的語(yǔ)言都會(huì)有一種內(nèi)置的判斷機(jī)制,有些語(yǔ)言會(huì)有一些內(nèi)置的先進(jìn)機(jī)制的前置條件,后置條件和不變量。在某些情況下,這些語(yǔ)言可以優(yōu)化一些判句,會(huì)留下一些在優(yōu)化過(guò)程中不能優(yōu)化的問(wèn)題,一個(gè)注解系統(tǒng)可以用靜態(tài)來(lái)實(shí)現(xiàn),一部分可以用動(dòng)態(tài)實(shí)現(xiàn);我先前對(duì)注釋系統(tǒng)的靜態(tài)應(yīng)用的評(píng)論。

  暫時(shí)增強(qiáng)系統(tǒng)邏輯斷言是一個(gè)更為先進(jìn)的使用暫時(shí)斷句的研究方法。你可以在http://www.cl.cam. ac.uk/research/security/ctsrd/tesla/.網(wǎng)站上發(fā)現(xiàn)更多的信息。

  不用懷疑斷句可以有一個(gè)極好的機(jī)制來(lái)用于檢測(cè)無(wú)效狀態(tài),無(wú)效狀態(tài)有時(shí)是一個(gè)最弱的指標(biāo)。

  然而,這中方法在涉及到對(duì)抗心臟出血漏洞時(shí)確實(shí)有些不足。不論是原開(kāi)發(fā)商或是檢查的人意識(shí)到檢查請(qǐng)求報(bào)文的長(zhǎng)度值是很重要的;因?yàn)闆](méi)有使用長(zhǎng)度檢查,開(kāi)發(fā)者是不能添加判據(jù)來(lái)檢查它。這是一個(gè)在進(jìn)行negative測(cè)試時(shí)的問(wèn)題,但是negative測(cè)試可以通過(guò)分割這些要開(kāi)放的功能的代碼來(lái)簡(jiǎn)單的實(shí)現(xiàn),很容易證明所有的數(shù)據(jù)字段都在進(jìn)行檢查,所以我感覺(jué)negative測(cè)試會(huì)更有可能發(fā)現(xiàn)存在漏洞的類(lèi)型。因此,雖然積極的注釋可以很有效的對(duì)抗漏洞,在某種程度上它會(huì)在特定的情況下工作。

  我把這種方法看作是一個(gè)較為復(fù)雜的選擇。使用這種方法可以檢測(cè)到心臟出血漏洞,需要積極使用判據(jù)。增加這些判據(jù)要使用大量的開(kāi)發(fā)時(shí)間和提高運(yùn)行的成本。

  3.8 更安全的語(yǔ)言

  心臟出血漏洞產(chǎn)生的原因是C語(yǔ)言不包含有任何的內(nèi)部檢測(cè)或是方法來(lái)對(duì)抗緩沖區(qū)不當(dāng)?shù)南拗啤2磺‘?dāng)?shù)南拗茣?huì)導(dǎo)致災(zāi)難性的問(wèn)題,所以幾乎所有其他的編程語(yǔ)言都會(huì)自動(dòng)對(duì)抗不正當(dāng)?shù)南拗啤?/p>

  如果在一個(gè)給定的程序中的漏洞可以造成災(zāi)難性的影響,那么選擇它的程序語(yǔ)言時(shí)更應(yīng)該減少漏洞存在的可能性。越是災(zāi)難性的影響,就越要有更好的表現(xiàn)。大多數(shù)的程序語(yǔ)言提供對(duì)其他危險(xiǎn)漏洞的保護(hù)措施,如不恰當(dāng)?shù)南拗票Wo(hù)。某些程序語(yǔ)言有更小的可能性出現(xiàn)被誤用和不正確使用的結(jié)構(gòu)。理想情況下,一種語(yǔ)言將會(huì)阻止所有漏洞。通用的語(yǔ)言都不能阻止所有的漏洞,但是它是編程者爭(zhēng)取的一個(gè)目標(biāo)。沒(méi)有“絕對(duì)安全”的程序語(yǔ)言;它是一個(gè)繼續(xù)發(fā)展的事物,一些語(yǔ)言提供了更多的對(duì)策。

  3.8.1 危險(xiǎn)語(yǔ)言和為什么使用他們

  最廣泛使用的與安全有關(guān)的軟件有C,C + +和Objective-C。所有的這些語(yǔ)言都沒(méi)有提供緩沖區(qū)的訪問(wèn)限制,實(shí)際上,它要通過(guò)努力來(lái)限制緩沖區(qū)讀和寫(xiě)溢出的出現(xiàn)。對(duì)緩沖區(qū)訪問(wèn)的不恰當(dāng)?shù)南拗茣?huì)被廣泛使用類(lèi)型的災(zāi)難性的影響漏洞。使用或是轉(zhuǎn)變成其他的語(yǔ)言將會(huì)消除緩沖區(qū)的漏洞,包括心臟出血漏洞。C語(yǔ)言更是這樣,因?yàn)樗狈芏嗫梢员苊饩彌_區(qū)出現(xiàn)問(wèn)題的高級(jí)結(jié)構(gòu)。大多數(shù)語(yǔ)言也可以防止內(nèi)存釋放錯(cuò)誤,可能會(huì)導(dǎo)致安全漏洞,以及一些語(yǔ)言也會(huì)被設(shè)計(jì)成對(duì)抗其他漏洞。其中在現(xiàn)在系統(tǒng)中有很多漏洞的原因之一是C、C++、和Objective-C語(yǔ)言的過(guò)度使用。實(shí)際上,有人提出禁止在安全性敏感的代碼中使用這些語(yǔ)言。

  C、C++、和Objective-C語(yǔ)言的廣泛使用是有原因的。在TIOBE編程區(qū)域指數(shù)來(lái)衡量的編程語(yǔ)言的流行,2014年4月占到了使用人數(shù)的前四。這些原因包括更高的性能和界面簡(jiǎn)單,大型的存儲(chǔ),更好的表現(xiàn),熟悉性。此外,把語(yǔ)言轉(zhuǎn)變成大型程序是需要很大的努力。讓我們來(lái)看看原因。

  3.8.2 替代產(chǎn)品的運(yùn)行速度和內(nèi)存性能

  一個(gè)經(jīng)常被引用的問(wèn)題是使用C,C++,和Objective-C比其他的程序的運(yùn)行速度快。此外,當(dāng)要和硬件連接時(shí),其他語(yǔ)言就會(huì)缺乏最底層的機(jī)制。如果你要很快的速度,你可以直接連接,語(yǔ)言列表中的運(yùn)行時(shí)間會(huì)更短。運(yùn)行速度直接決定著移動(dòng)設(shè)備和服務(wù)器領(lǐng)域。基準(zhǔn)游戲中速度分析程序是使用不同的語(yǔ)言編寫(xiě)的。“程序語(yǔ)言編程的大致等級(jí)”中說(shuō)到,發(fā)送數(shù)據(jù)和不同語(yǔ)言的包是根據(jù)他們的大致速度來(lái)實(shí)現(xiàn)。沒(méi)有完美的基準(zhǔn),它始終是一個(gè)最好的衡量績(jī)效的具體方法。不過(guò),我更喜歡數(shù)字的大致猜測(cè),這個(gè)數(shù)據(jù)即足夠代表開(kāi)始。如果性能是你要追求的,你不想使用匯編語(yǔ)言,可以考慮下下面的分析:

  Fortran。Fortran的應(yīng)用表現(xiàn)經(jīng)常要比其他的語(yǔ)言好,尤其是在數(shù)值計(jì)算上。但是,我不清楚很多人會(huì)把很多的代碼轉(zhuǎn)變成更原始的編程語(yǔ)言。特別是據(jù)我所知,即使是現(xiàn)代Fortran也沒(méi)有和低級(jí)的硬件的接口的標(biāo)準(zhǔn)機(jī)制。

  Ada。Ada用于真實(shí)時(shí)間系統(tǒng)的應(yīng)用,因此,它會(huì)有更好的性能,包括訪問(wèn)底層的組件。Ada可以用于對(duì)抗錯(cuò)誤,在編譯時(shí)表現(xiàn)的最好,它的語(yǔ)法是專門(mén)用于對(duì)付錯(cuò)誤的,Ada一定能對(duì)抗緩沖區(qū)的心臟出血漏洞。很多人都不喜歡像Ada一樣的語(yǔ)言,因?yàn)锳da要很?chē)?yán)格的靜態(tài)類(lèi)型檢查,但是這中檢查是發(fā)現(xiàn)缺陷的關(guān)鍵機(jī)制之一。Ada一般廣泛的應(yīng)用在像航空鐵路等這些高保障的地方。

  ATS。這不是一種眾所周知的廣泛使用的編程語(yǔ)言,但是它確實(shí)非常成功的應(yīng)用在特定的基準(zhǔn)測(cè)試套件上。我要指出ATS不在最近使用的程序列表上。

  還有很多其他的編程語(yǔ)言,特別當(dāng)你愿意放棄由基準(zhǔn)確定的速度時(shí)。例如Go的性能就很好。Rust是另一種你可以考慮的程序語(yǔ)言。Java在當(dāng)前的JITs上有很合理的表現(xiàn),一旦它運(yùn)行起來(lái),但是這有個(gè)一個(gè)特別的啟動(dòng)時(shí)間。其他的語(yǔ)言在基準(zhǔn)下也很有用,如Scala,F(xiàn)ree Pascal,Lisp SBCL,Haskell, C# on Mono, F# on Mono, and OCaml。不論是D編程語(yǔ)言還是Nimrod語(yǔ)言都列出了相應(yīng)的標(biāo)桿。但是使用他們時(shí)也要考慮到效率問(wèn)題。

  當(dāng)然,如果速度不是關(guān)鍵,很多的軟件都能被使用。一個(gè)研究表明,用.NET, Java, ASP, PHP, Cold Fusion和Perl來(lái)編寫(xiě)的程序中的靜態(tài)漏洞沒(méi)有統(tǒng)計(jì)學(xué)上差異。所有這語(yǔ)言要比C,C++或是Objective-C安全。因此所有人都可以防止緩存溢出的問(wèn)題。

  這有太多的編程語(yǔ)言可以使用,我就在這多說(shuō)了點(diǎn)。我的目的不是列出說(shuō)所有可以替代的編程語(yǔ)言,而是讓人們知道是有替代的存在。

  性能不單單是速度,還有內(nèi)存的管理。在移動(dòng)設(shè)備上尤為重要。C, C++和Objective-C沒(méi)有自動(dòng)垃圾收集器,但是其他的語(yǔ)言有這個(gè)功能。開(kāi)發(fā)人員如果不考慮內(nèi)存管理時(shí),他們考慮的是效率,但是在很多的環(huán)境下是不現(xiàn)實(shí)的。Drew Crawford對(duì)移動(dòng)設(shè)備的發(fā)展做了很長(zhǎng)時(shí)間的研究,他指出“如果你需要至少6倍的內(nèi)存,自動(dòng)垃圾收集工作會(huì)很管用,但是如果這里少于4倍的內(nèi)存,會(huì)減少效率。”iOS基于人工操作的大多數(shù)事情的文化,并且試圖讓編譯器做一些簡(jiǎn)單的東西。Android基于他們努力不在實(shí)踐中應(yīng)用垃圾收集器工作,但是不論哪種方式,當(dāng)他們編寫(xiě)移動(dòng)應(yīng)用程序時(shí),每個(gè)人都花了很多時(shí)間考慮內(nèi)存管理。內(nèi)存是不可以替代的。OS X Mountain Lion v10.8中廢棄了自動(dòng)垃圾收集器,在以后的版本中會(huì)把它刪除。都推薦使用自動(dòng)引用算法。不是像OS X和iOS一樣。這就是人們選擇C, C++,和Objective-C的原因。

  C, C++, 和 Objective-C編寫(xiě)的程序比其他的語(yǔ)言的運(yùn)行性能好嗎?回答就是語(yǔ)言就被設(shè)計(jì)成這樣。特別是C語(yǔ)言編寫(xiě)的程序能夠快速的運(yùn)行并且使用很少的內(nèi)存;C語(yǔ)言中指出C的關(guān)鍵是“相信程序員”,“許多操作被定義為如何在目標(biāo)機(jī)器的硬件上使用它”。另外,C的模型是透明的,所以C或是C++開(kāi)發(fā)人員可以使用它,通常評(píng)估一個(gè)結(jié)構(gòu)。當(dāng)然,現(xiàn)實(shí)會(huì)有很大的差距;大量?jī)?yōu)化的編譯器和運(yùn)行時(shí)間要比一般的情況下有更好的性能。

  很多的開(kāi)發(fā)者選擇C, C++,或是Objective-C來(lái)簡(jiǎn)化其他組件的接口。許多工具都有C的接口,大多數(shù)語(yǔ)言的基礎(chǔ)設(shè)施都可以通過(guò)C語(yǔ)言的庫(kù)。然而,許多其他的編程語(yǔ)言都有C的接口,兩種方法為C路徑和其他系統(tǒng)通過(guò)接口來(lái)調(diào)用。因此,這并不重要,重要的理由是選擇哪種語(yǔ)言。

  當(dāng)使用C, C++,和Objective-C的開(kāi)發(fā)人員使用這些語(yǔ)言時(shí)可以減少使用庫(kù)的危險(xiǎn)。最新的C標(biāo)準(zhǔn)還增加了一些安全功能,尤其是那些對(duì)字符段的處理。C標(biāo)準(zhǔn)仍然錯(cuò)誤的提供易于使用動(dòng)態(tài)調(diào)整大小函數(shù)的asprintf()或是類(lèi)似的函數(shù)。但是很多現(xiàn)在的系統(tǒng)使用asprintf()。C語(yǔ)言也可以使用GString類(lèi)型的glib庫(kù),strlcpy/strlcat提供,或是其他解決問(wèn)題中的一個(gè)。C++程序可以使用std::string或是它的類(lèi)似內(nèi)容。類(lèi)似,Objective-C具有NSString和NSMutableString類(lèi)。但是這些設(shè)施只能在一定程度上降低風(fēng)險(xiǎn);即使使用了這些設(shè)備犯了錯(cuò)誤。

  你可以用什么語(yǔ)言來(lái)寫(xiě)不安全軟件。例如,SQL注入的漏洞是另一個(gè)普通弱點(diǎn),而這可能使用每種語(yǔ)言。然而,大多數(shù)語(yǔ)言提供的易于使用,和避免發(fā)生問(wèn)題的機(jī)制。我要很小心的使用這個(gè)機(jī)制…但是對(duì)C, Java,和其他語(yǔ)言來(lái)說(shuō)的。

  有些語(yǔ)言通常是通過(guò)計(jì)數(shù)器緩沖區(qū)溢出,讓你暫時(shí)停止保護(hù)逃逸機(jī)制。這些逃逸機(jī)制很容易發(fā)現(xiàn)和與精心寫(xiě)的代碼隔離開(kāi)來(lái)。他們把不安全的隔離成很小的部分,從而降低風(fēng)險(xiǎn)。在很多情況下,你可以重新實(shí)現(xiàn)內(nèi)存緩沖區(qū)高速緩存;你可以啟動(dòng)一些漏洞即使緩沖區(qū)存在保護(hù)時(shí)。但是這種重新實(shí)現(xiàn)是明顯的,在很多的語(yǔ)言中,人們必須要努力避免緩沖區(qū)溢出問(wèn)題。與其相反的是,在C, C++, 和 Objective-C里,你必須做一些附加的工作來(lái)避免這種問(wèn)題。

  創(chuàng)建安全軟件時(shí),也會(huì)遇到一些附加的挑戰(zhàn)。我知道沒(méi)有辦法安全的擦除Java里的數(shù)據(jù)。這是因?yàn)镴ava里沒(méi)有.NET的SecureString的功能;由于內(nèi)存分配和垃圾收集器怎么實(shí)現(xiàn)多次拷貝,Java的結(jié)構(gòu)是在結(jié)束在內(nèi)存中。這不是Java的特點(diǎn),很難安全擦除數(shù)據(jù)在多種語(yǔ)言中。但是Java中,它可以比較容易通過(guò)建立一個(gè)小的非Java模塊來(lái)擦除一些數(shù)值;該程序的其余部分仍然受到保護(hù)不會(huì)出現(xiàn)緩沖溢出。此外,利用額外的內(nèi)存拷貝需要訪問(wèn)大量的程序和運(yùn)行環(huán)境。安全擦除往往是一個(gè)有用的減少損傷的措施。相比之下,緩沖區(qū)溢出有時(shí)候可以直接減少可以利用的連接,有時(shí)只要通過(guò)網(wǎng)絡(luò)連接。一般情況下,緩沖區(qū)溢出要比大多數(shù)其他語(yǔ)言帶來(lái)的問(wèn)題更危險(xiǎn)。

  這很難使用C, C++, 和 Objective-C來(lái)編寫(xiě)安全軟件。大多數(shù)的語(yǔ)言都可以內(nèi)嵌和防止緩沖區(qū)溢出保護(hù)…但是C, C++, 和Objective-C例外。另一方面,他們使用這種原因。

  開(kāi)始運(yùn)行每一個(gè)新的安全相關(guān)程序,就要仔細(xì)的考慮下程序語(yǔ)言。選擇一個(gè)更安全的語(yǔ)言是很有必要的,這樣就可以去除潛在的安全漏洞,其中包括緩沖區(qū)溢出的心臟出血漏洞。另外,計(jì)算機(jī)變得更加強(qiáng)大,在很多情況下可以進(jìn)行交易一些性能。更重要的是,在開(kāi)始編寫(xiě)新的程序時(shí),使用另外一種編程語(yǔ)言就幾乎變成了零成本。我相信用不太安全的語(yǔ)言時(shí),和重寫(xiě)代碼需要花費(fèi)很多努力。但是,使用幾乎任何不是C, C++,或是Objective-C,至少會(huì)消除緩沖區(qū)溢出和緩沖區(qū)溢出漏洞會(huì)有很大的影響。

  我已經(jīng)確定了更安全的語(yǔ)言作為一個(gè)更復(fù)雜的方法,因?yàn)榍袚Q一個(gè)不常用的程序,用不同的語(yǔ)言來(lái)實(shí)現(xiàn)安全是要花費(fèi)很多的時(shí)間的。

  3.8 完全靜態(tài)分析器

  一個(gè)完全的靜態(tài)分析器可以被稱為聲音靜態(tài)分析器,用來(lái)發(fā)現(xiàn)某個(gè)特定的漏洞。創(chuàng)建這些類(lèi)型的工具就是在調(diào)整C語(yǔ)言。然而,程序有時(shí)不得不限制他們使用的架構(gòu),并且開(kāi)發(fā)人員必須提供附加的注解資料。因?yàn)檫@些工具集中發(fā)現(xiàn)一切問(wèn)題,他們往往會(huì)報(bào)告不存在漏洞,這就必須要分析決定是否真的存在漏洞。但是,如果它應(yīng)對(duì)所有的漏洞,權(quán)衡是很有必要的。

  3.9 完全認(rèn)為的核對(duì)

  一個(gè)完全徹底不獨(dú)立的人為軟件檢查,主要集中在確保安全性和發(fā)現(xiàn)漏洞,這是發(fā)現(xiàn)漏洞的最佳方式。這些評(píng)論又被稱為審核,在展示時(shí),這個(gè)軟件是很脆弱的。

  它的觀念是通過(guò)人為審核要比通過(guò)工具的啟發(fā)式技術(shù)來(lái)查找漏洞更直觀。更重要是實(shí)驗(yàn)數(shù)據(jù)證實(shí)了這一點(diǎn)。例如,Kupsch和Miller發(fā)現(xiàn)使用第一原理弱點(diǎn)評(píng)估方式的人為審計(jì)分析一個(gè)示例程序比使用Coverity Prevent和Fortify Source Code Analyzer更全面。人為審核也會(huì)出現(xiàn)意外,但是這樣的評(píng)估會(huì)做的相當(dāng)不錯(cuò)。在Kupsch實(shí)驗(yàn)室,F(xiàn)PVA人為檢查發(fā)現(xiàn)了15個(gè)嚴(yán)重的安全漏洞;Fortify發(fā)現(xiàn)了6個(gè),Coverity發(fā)現(xiàn)了1個(gè),既不是自動(dòng)化工具發(fā)現(xiàn)也不是由人的審查發(fā)現(xiàn)。

  但是人工核查的缺點(diǎn)也是顯而易見(jiàn)的:這需要努力和專業(yè)知識(shí)來(lái)做這樣的審核,改變也要審核。人為審查不適合用于所有的軟件,甚至當(dāng)它在面臨很復(fù)雜的情況時(shí)。

  請(qǐng)注意,這種審核和以前的可以接受的典型的、簡(jiǎn)單的回顧是不同的。心臟出血漏洞是試圖避免漏洞開(kāi)發(fā)人員發(fā)現(xiàn)的,被另一個(gè)審核接受。然而,補(bǔ)丁的審核通常是是功能的改善和尋找安全漏洞的過(guò)程,所以很容易讓他們錯(cuò)過(guò)漏洞。正如前面提到的,人為審查每個(gè)補(bǔ)丁來(lái)要求每個(gè)領(lǐng)域的有效認(rèn)證,要抓住這點(diǎn)…但是現(xiàn)在代碼的存在,只是審核新的補(bǔ)丁是不夠的。試圖在這一點(diǎn)上單獨(dú)審查每一份文件的補(bǔ)丁可能是不符合成本效應(yīng)的。此外,補(bǔ)丁的審核可能錯(cuò)過(guò)重要問(wèn)題。一個(gè)單獨(dú)的審核關(guān)注整個(gè)系統(tǒng)的漏洞是很有效的。

  這種審核確實(shí)可以發(fā)現(xiàn)。事實(shí)上,在心臟出血漏洞被發(fā)現(xiàn)的同時(shí),TrueCrypt的一個(gè)重要組成部分的安全審查發(fā)布了。

  在很多情況下軟件應(yīng)該進(jìn)行修改和簡(jiǎn)化,在審查之前。我認(rèn)為對(duì)于OpenSSL是尤其重要的。那些復(fù)雜的程序都很難為工具和人為的評(píng)估。OpenSSL使用的復(fù)雜結(jié)構(gòu),這就讓它很難被人和機(jī)器發(fā)現(xiàn)。

  3.10格式化方法

  但是如果你真的想在某種程度上肯定什么是這個(gè)程序要做的?存在著一系列的方法叫做“格式化方法”,這要比上面列出的技術(shù)方法更有信心。格式化的方法包括使用“嚴(yán)格的數(shù)學(xué)技術(shù)和工具來(lái)規(guī)范、設(shè)計(jì)和驗(yàn)證軟件和硬件系統(tǒng)。”由于使用格式化方法是有困難的,他們更可能是在目前的小程序和模塊上,是絕對(duì)可以使用格式化方法的。此外,如果你真的想要擁有很高的信任程序,格式化的方法仍然是實(shí)現(xiàn)這一信心的唯一途徑。

  這有很多方面可以使用格式化方法。有些人只用格式化的方法來(lái)創(chuàng)建規(guī)范,不會(huì)使用格式化的方法來(lái)多做什么。有些人可能會(huì)想的多一點(diǎn),證明有關(guān)規(guī)范的一些聲明或是改進(jìn)的規(guī)范走向更具體的模型。這些方法都不會(huì)發(fā)現(xiàn)心臟出血漏洞。對(duì)于心臟出血漏洞來(lái)說(shuō),格式化方法要?jiǎng)?chuàng)造關(guān)于代碼的證明,在源代碼和可執(zhí)行代碼水平上,這就是我最關(guān)心的。

  在關(guān)于有關(guān)代碼注釋的系統(tǒng)的實(shí)踐證明,值得一提的是,注解系統(tǒng)通常可以在各種不同的方式來(lái)使用簡(jiǎn)化的證明。為了了解更多的信息,請(qǐng)參見(jiàn)我有關(guān)注釋系統(tǒng)的評(píng)論。

  如果你對(duì)更多的感興趣,特別是支持格式化的FLOSS工具,請(qǐng)參閱從我的類(lèi)的格式化方法來(lái)開(kāi)發(fā)安全的軟件。一個(gè)有趣的格式化方法工具套件是Toccata,它結(jié)合了Frama-C和Why3,以及許多自動(dòng)化和互助工具。通過(guò)組合這些不同的工具來(lái)證明程序的正確,在比以前使用更少的努力。更重要的是,他們可以處理C的大量子集;而最正規(guī)的方法是不能做到的。SPARK 2014就是基于Ada的,但是可以讓你證明相關(guān)程序的聲明,以及他們最近和Toccata聯(lián)系在了一起。

  正式驗(yàn)證程序的實(shí)例中有seL4,CompCert C,cakeML,Tokeneer和iFACTS。

  四、前提條件

  很多的技術(shù)有重要的先決條件;讓我們來(lái)討論下。

  4.1 在沒(méi)有特別要求時(shí)內(nèi)存分配

  許多靜態(tài)技術(shù)可以對(duì)抗心臟出血漏洞的缺陷,包括使用人工核查來(lái)對(duì)抗,因?yàn)镺penSSL的代碼很復(fù)雜。代碼只有簡(jiǎn)單了才能安全。

  許多安全軟件開(kāi)發(fā)者首先使用“軟件質(zhì)量”工具來(lái)檢測(cè)特別復(fù)雜的結(jié)構(gòu),然后簡(jiǎn)化這些結(jié)構(gòu),這就是安全軟件的產(chǎn)生過(guò)程。理想的靜態(tài)分析方法由于代碼復(fù)雜和變得困難,實(shí)用工具來(lái)檢測(cè)這些代碼的復(fù)雜性,簡(jiǎn)化他們,在使用靜態(tài)分析方法就變得很有效。我認(rèn)為他們是對(duì)的,但是我沒(méi)有發(fā)現(xiàn)可以支持他們的數(shù)據(jù)。因此,這似乎是一個(gè)合理的想法,但是我很希望有人最終將創(chuàng)建并發(fā)布一些科學(xué)研究來(lái)支持和反駁這個(gè)假設(shè)。

  在任何情況下,簡(jiǎn)化的代碼是超過(guò)運(yùn)行工具軟件的。這是一種心態(tài),應(yīng)該要有不斷的努力來(lái)簡(jiǎn)化代碼,不然增加運(yùn)行能力就會(huì)增加軟件的復(fù)雜性。代碼的重構(gòu)要使它變的更簡(jiǎn)單和清晰,不是不斷的增加新的功能。我們的目標(biāo)是代碼是對(duì)的,而不是代碼很復(fù)雜我們看不出問(wèn)題。

  過(guò)于復(fù)雜的代碼通常會(huì)導(dǎo)致安全漏洞。2006年Debian意外事件通過(guò)修改軟件來(lái)消除valgrind警告來(lái)打破OpenSSL的隨機(jī)數(shù)生成器。但是,修改軟件的人并不真正的了解它。那個(gè)人要求幫助,但是OpenSSL的代碼復(fù)雜就很難使人找到改變后的漏洞。Cox通過(guò)研究發(fā)生并得到了以下的結(jié)論:“盡量不寫(xiě)偷懶的代碼,寫(xiě)井井有條的代碼。你會(huì)不可避免的寫(xiě)一些偷懶沒(méi)有組織的代碼。如果有人問(wèn)到這這個(gè)問(wèn)題,就把它作為代碼不夠好的標(biāo)志。重新把它變得更簡(jiǎn)單和容易理解。”

  LibreSSL的開(kāi)發(fā)者使用了OpenSSL代碼和專心用來(lái)簡(jiǎn)化代碼。LibreSSL-一個(gè)OpenSSL的變版,介紹OpenSSL代碼庫(kù)的一些問(wèn)題。他們正在做許多的明智的事,如去掉代碼支持過(guò)時(shí)的VAX VMS系統(tǒng)。然而,他們刪除了人們關(guān)心的代碼。例如,他們?nèi)コ绹?guó)政府使用的FIPS 140-2的認(rèn)證,這同時(shí)也受到了許多民營(yíng)企業(yè)的支持。在使代碼變得簡(jiǎn)單和使代碼在很多的環(huán)境中都有效之間存在著沖突,最簡(jiǎn)單的代碼不能實(shí)現(xiàn)什么。很顯然,許多程序可以變得比現(xiàn)在簡(jiǎn)單。

  4.2 簡(jiǎn)化應(yīng)用程序接口

  雖然這稍微的超出了本文的范圍,一個(gè)相關(guān)的問(wèn)題就是應(yīng)用程序接口一般情況下都比較復(fù)雜。

  大多數(shù)加密庫(kù)和數(shù)據(jù)傳輸庫(kù)都是很復(fù)雜的,他們通常呈現(xiàn)給開(kāi)發(fā)者一個(gè)“困惑矩陣的選項(xiàng)和設(shè)置”,因此,大量的應(yīng)用程序和高層次的庫(kù)使用不正確的庫(kù)來(lái)進(jìn)行加密,導(dǎo)致了系統(tǒng)的漏洞。大都數(shù)的問(wèn)題在瀏覽器中工作中出現(xiàn),但是他們?cè)谄渌拇a上仍然是一個(gè)問(wèn)題。想要了解更多的信息,請(qǐng)看“最危險(xiǎn)的代碼世界:在非瀏覽器軟件中驗(yàn)證SSL證書(shū)。”

  盡管這在SSL/TLS的使用中是一個(gè)技術(shù)而不是一個(gè)漏洞,但是他們是無(wú)關(guān)的。加密程序庫(kù)是創(chuàng)建的復(fù)雜接口的一個(gè)組件,所以,它仍然是一個(gè)故障組件,簡(jiǎn)化代碼。

  一個(gè)相關(guān)問(wèn)題是底層庫(kù)和建立在API加密庫(kù)的系統(tǒng)的很難使用。C忽略了像asprintf和reallocarray等功能。因此,程序員必須要解決這些漏洞,但是他們的解決方法常常會(huì)出現(xiàn)bug,這些bug會(huì)導(dǎo)致漏洞。

  4.3 分配和釋放內(nèi)存

  安全的程序必須正常的分配和釋放內(nèi)存,沒(méi)有特別的分配系統(tǒng)和內(nèi)存緩存系統(tǒng)。至少,它應(yīng)該很容易禁用和測(cè)試它們來(lái)確保禁用了他們的程序。一些技術(shù)會(huì)減輕心臟出血漏洞的出現(xiàn),因?yàn)镺penSSL的內(nèi)存分配方式。

  基本問(wèn)題是OpenSSL包括未分配的內(nèi)存的應(yīng)用程序特定的緩存空間。目的就是要加快分配在相同數(shù)量的重復(fù)指令。在默認(rèn)情況下,OpenSSL正常分配內(nèi)存,但是在內(nèi)存區(qū)域沒(méi)有被使用時(shí)是不會(huì)解除分配的,在很多情況下,把該區(qū)域變成未使用的區(qū)域變成空閑的,來(lái)使它可以立刻重啟。這個(gè)緩存列表顛覆了一些操作系統(tǒng)和C的運(yùn)行的一些的機(jī)制,因?yàn)樗麄儾⒉皇强偟玫酵ㄖ趦?nèi)存不使用時(shí)。

  Theo de Raadt提到:“幾年前我們?cè)黾永么胧┑絣ibc malloc和mmap,這樣一來(lái)更多的bugs就會(huì)暴露出來(lái)。這種存儲(chǔ)器會(huì)導(dǎo)致死機(jī),甚至是核心的崩潰。分析這些bug,之后永久的維護(hù)系統(tǒng)。其他的調(diào)試工具也會(huì)達(dá)到這個(gè)目的。在很大的程度上說(shuō),這基本就沒(méi)有性能上的損失。但是在那個(gè)時(shí)候OpenSSL添加了malloc & free的封裝,使庫(kù)存在緩存中。因?yàn)橐恍┢脚_(tái)的性能下降,甚至如果你建立防護(hù)技術(shù)引入malloc() 和free(),這就無(wú)效了。在所有平臺(tái)上,由于選項(xiàng)是默認(rèn)的,并且Ted的測(cè)試表明你不能關(guān)掉它。因?yàn)樗麄儧](méi)有測(cè)試它的年齡。所以后來(lái)的bug顯示了在該層的內(nèi)存的泄漏內(nèi)容。如果內(nèi)存通過(guò)free得到了恰當(dāng)?shù)姆祷兀@就可能被munmap捕捉到,并激發(fā)保護(hù)程序的崩潰而不是泄漏你的密碼。”

  似乎有很多在什么地方出來(lái)問(wèn)題的困惑和OpenSSL的內(nèi)存分配方法,Chris Rohlf取得了一些有益的驗(yàn)證。我覺(jué)得這些驗(yàn)證是很重要的,因?yàn)槲覀儽仨毾扔美斫膺@個(gè)問(wèn)題在我們修護(hù)它之前。特別是Rohlf指出OpenSSL使用的是標(biāo)準(zhǔn)的malloc() C內(nèi)存分配方式,當(dāng)它需要一個(gè)全新的內(nèi)存塊時(shí)。問(wèn)題是一旦一個(gè)內(nèi)存塊被分配,OpenSSL自身還在自身的管理存儲(chǔ)器。Rohlf也指出在很多的環(huán)境下是與空閑列表是無(wú)關(guān)的;一個(gè)空閑列表把不同的內(nèi)存分配在了一起,但是許多典型的內(nèi)存分配系統(tǒng)也提出了不同的內(nèi)存分配。然而,Rohlf的典型的內(nèi)存分配的應(yīng)用來(lái)做同樣的事是絕對(duì)正確的,關(guān)鍵是OpenSSL的實(shí)現(xiàn)阻礙了各種緩解措施。關(guān)于OpenSSL的內(nèi)存分配系統(tǒng)有另一個(gè)問(wèn)題,但是我們首先要介紹下一些基本知識(shí)。

  一般的方法就是處理一些內(nèi)存的分配和釋放特例,我們的想法就是緩存和重新對(duì)某些對(duì)象和緩存器在他們沒(méi)有被使用時(shí),這中方法可以顯著的提高性能。這種方法的具體例子包括專門(mén)處理共同的內(nèi)存分配的大小,或是用未使用的高速緩存來(lái)重新使用對(duì)象和內(nèi)存器。有一些具體的技術(shù)來(lái)做這些,包括創(chuàng)建一個(gè)對(duì)象池和一個(gè)slab分配器。Glib庫(kù)包括一個(gè)稱為記憶切片的機(jī)制,提高內(nèi)存的分配性能。許多圖形用戶界面和程序在使用這些方法時(shí),是沒(méi)有安全感的。

  事實(shí)證明,一些方法可以不用解決一些檢測(cè)工具如address sanitizer和使用保護(hù)頁(yè)系統(tǒng)。特別是使用fuzz測(cè)試的問(wèn)題,如果這些工具不被禁用,則fuzz測(cè)試就會(huì)變得沒(méi)有效果了。的確,fuzz測(cè)試可能不能檢測(cè)到許多超出范圍的讀操作,在使用這些方法時(shí)。

  關(guān)于OpenSSL的報(bào)告指出OpenSSL的使用是自我管理的一個(gè)交大的內(nèi)存區(qū)域的方法然后在進(jìn)一步細(xì)化。這是一個(gè)使用slab分配器或是儲(chǔ)存器切片時(shí)要發(fā)生的。使用這個(gè)方法就是想要提高性能,在這些情況下使用address sanitizer和保護(hù)頁(yè)系統(tǒng)來(lái)抑制檢測(cè)完全的讀溢出。舊的版本稱這要發(fā)生什么。但是我已經(jīng)鉆研了更多的OpenSSL代碼,而這似乎并沒(méi)有在OpenSSL中的真實(shí)性。這對(duì)于心臟出血漏洞來(lái)說(shuō)是個(gè)好消息。盡管如此,這些類(lèi)型的分配方案是比較常見(jiàn)的,而且我知道沒(méi)有人說(shuō)道這些方法的風(fēng)險(xiǎn)。

  安全性軟件必須要避免使用內(nèi)存緩存系統(tǒng),尤其是那些與一種分配機(jī)制聯(lián)合在一起形成一個(gè)分配請(qǐng)求。如果不是這樣的話,他們至少提供一個(gè)簡(jiǎn)單的證據(jù)機(jī)制來(lái)禁用它們,并要使用該機(jī)制作為其回歸測(cè)試套件的一部分。OpenSSL有一個(gè)禁用機(jī)制,但是不再被使用,并且在任何情況下很少有人能了解這種機(jī)制,它可以禁用安全分析工具的很多工程。

  我們還需要修改我們的教育材料,是開(kāi)發(fā)人員和測(cè)試人員都知道內(nèi)存緩存系統(tǒng)會(huì)嚴(yán)重妨礙安全分析。在我的演講中我已經(jīng)提出了一些材料來(lái)開(kāi)發(fā)安全軟件,其他人員也一樣需要。

  從長(zhǎng)遠(yuǎn)來(lái)看,這或許應(yīng)該是使用C的標(biāo)準(zhǔn)接口在freelists緩存/ slab分配器。如果有標(biāo)準(zhǔn)的接口,你們工具可以很容易的修改和自動(dòng)調(diào)解他們。

  4.4 使用標(biāo)準(zhǔn)的FLOSS許可證

  這是我的推測(cè),我相信如果OpenSSL使用標(biāo)準(zhǔn)的推廣的許可證來(lái)進(jìn)行代碼審核會(huì)有更多的貢獻(xiàn)發(fā)生。OpenSSL使用的奇怪的變量許可證是GPL和LGPL。因?yàn)镚PL是一個(gè)最常見(jiàn)的FLOSS許可證。在很多情況下這種不相容性是通過(guò)圍繞一個(gè)許可證漏洞的,或是使用許可證除了在軟件中通過(guò)使用OpenSSL。不過(guò)這個(gè)詭異的證書(shū)意味著很多人更喜歡GPL或LGPL會(huì)情不自禁的禁止或是審核OpenSSL。一些人喜歡限制較少的許可證,這些也有很少的幫助,這不是一個(gè)標(biāo)準(zhǔn)的證書(shū)。

  我確實(shí)有一些證據(jù)表明非標(biāo)準(zhǔn)證書(shū)是一個(gè)問(wèn)題。一個(gè)完全獨(dú)立的軟件包GnuTLS在最初是專門(mén)創(chuàng)建的。因此使用標(biāo)準(zhǔn)GPL許可證的軟件能夠輕易的使用SSL/TLS。OpenSSL的LibreSSL轉(zhuǎn)變成了2-clause BSD許可證,當(dāng)他們寫(xiě)了新的代碼,相比與OpenSSL許可證。

  在很長(zhǎng)的一段時(shí)間了,廣泛的使用FLOSS證書(shū)對(duì)FLOSS項(xiàng)目來(lái)說(shuō)是很重要的。1999年Bruce Perens指出:“如果使用這里被列出的一個(gè),就不用寫(xiě)新的許可證了。”后來(lái)Open Source Initiative創(chuàng)建了License Proliferation Project,指出許多許可證“和其他開(kāi)源代碼的許可證是不兼容的,嚴(yán)重的限制了開(kāi)發(fā)人員的方法,開(kāi)發(fā)人員僅僅是擴(kuò)大開(kāi)源軟件的創(chuàng)新方式。”一個(gè)重要結(jié)果是OSI直接列出了開(kāi)源代碼許可證的頁(yè)面,只是Popular Licenses,這是“流行,廣泛使用,或是強(qiáng)大的社區(qū)。”

  大多數(shù)的FLOSS是基于GPL, LGPL, MIT/X, Revised BSD,BSD 2-Clause或是Apache 2.0 licenses。我建議限制FLOSS程序的許可證列表。你可以添加一些;在OSI的流行許可名單包括更多。然而,這里的問(wèn)題是OpenSSL許可證根本就不是一個(gè)公共無(wú)可證。更重要的是它是一個(gè)廣泛使用的不兼容的許可證的非標(biāo)準(zhǔn)證書(shū)。如果可能的話,最好用一般通用的許可證代替。

  五、什么會(huì)減少心臟出血漏洞的影響?

  什么能減少心臟出血漏洞的影響或是完全消除?畢竟當(dāng)漏洞出現(xiàn),你想減少影響。下面有一些方法。

  5.1 一旦標(biāo)準(zhǔn)內(nèi)存分配器被替代,啟用內(nèi)存分配器的防御。

  許多系統(tǒng)包括減少損壞的內(nèi)存分配機(jī)制,有的有時(shí)可以發(fā)現(xiàn)問(wèn)題。這不能對(duì)抗問(wèn)題,但是能夠減少影響,例如:

  一個(gè)常見(jiàn)的方法就是內(nèi)存在分配和釋放時(shí)零出,這就意味著如果數(shù)據(jù)顯示,這不太可能是有趣的事。

  在2014.4.29,David Wagner提出了一個(gè)有趣的選擇:“使用一個(gè)特定的內(nèi)存分配器,它能夠給每個(gè)對(duì)象一個(gè)隨機(jī)的地址。在一個(gè)64位系統(tǒng)上,會(huì)有一個(gè)48位的地址空間,這一切都在離分配對(duì)象遠(yuǎn)的地方,這個(gè)心臟出血漏洞不會(huì)透露任何其他對(duì)象的信息。這可以被納入標(biāo)準(zhǔn)內(nèi)存分配器。注明:我不主張這么做,我不是說(shuō)這是最好的防御,我只是回應(yīng)你的要求想法來(lái)阻止它。”

  OpenBSD的malloc支持保護(hù)頁(yè),如前所述。特別是它的G和P

上一篇:智能無(wú)懼挑戰(zhàn) 山石網(wǎng)科轟動(dòng)RSA2015

下一篇:研究發(fā)現(xiàn)密碼管理工具的嚴(yán)重安全缺陷