天天看點

權威黑客知識講座(二):漏洞的起源

  漏洞,通過非預期方法使用非法輸入使程式沒有按照既定規則運作,得到神奇的輸出結果。

因為漏洞的存在是以黑客才會樂此不疲地開發出對應的精簡,高效,優雅的代碼來對其進行攻擊和檢測。漏洞與程式的開發和測試息息相關。

      (一)何為程式

 所謂程式,是以一定輸入按照既定規則運作産生預期結果。聯系到現實生活中如:

1、烹饪(以一定的原材料按照工序處理産生美食)

2、自駕遊(通過駕駛員按照原定路線駛向目的地)

3、足球賽(一群球員按照比賽規則通過運球,傳球,射門赢得比賽)等等。

烹饪有菜單,駕駛有路線圖,踢球也有遊戲規則,同理計算機也一樣。

 由于計算機不懂人類語言,是以當人想與計算機溝通交流時,就要試着學會使用機器語言,然而機器語言對于常人來說非常的複雜且難以了解,機器語言由原始的位和位元組碼組成,而且随着計算機體系結構的不同而變化。

通常為了給某一個架構的CPU(如Intel X86)編寫程式,程式員不得不計算好與每一條指令相對應的值,了解指令之間是如何互動,以及許多其他的底層細節,是以這種晦澀複雜的開發語言注定不會被太多人所掌握。

翻譯程式的出現克服了機器語言程式面臨的困難,彙編就是典型的機器語言翻譯程式(當彙程式設計式運作時會自動翻譯成可識别的代碼程式),它使用不同的指令和變量命名取代了生澀的01機器碼,然而它卻遠遠不夠直覺,指令名依然深奧,依然與計算機體系結構密切相關(X86彙編語言的程式無法運作在Sparc處理器上,因為IntelX86與Sparc是截然不同的,程式遷移到其他平台隻能全部重寫),想要使寫出高效的彙程式設計式依然需要懂得許多關于處理器的底層細節。

1987年,SUN和TI公司合作開發了RISC微處理器——SPARC。SPARC微處理器最突出的特點就是它的可擴充性,這是業界出現的第一款有可擴充性功能的微處理。SPARC的推出為SUN赢得了高端微處理器市場的領先地位。

Sun是世界上第一個将RISC架構給以量産的廠商(親們,不要認為Sun隻有Java)。為了推動SPARC成為業界标準,并提高全球廣泛供應來源,SUN也授權多家半導體廠生産自己的SPARC晶片。SPARC的性能超強,價格也較高,公認在UNIX上的表現傑出。)

同類小知識:

如中國的星載計算機(在衛星上使用的計算機系統),就是用的Sparc處理器。在世界範圍内星載計算機系統中所使用的處理器架構隻有兩種,一種是由美國使用的POWERPC架構,另一種就是歐洲主導的SPARC架構。親覺得我們會用美國的POWERPC架構嗎?

 -----------------掃盲結束>

為了進一步解決翻譯程式的種種困難,人們把目光轉向了可以把進階語言翻譯成機器語言的編譯程式,進階語言與彙程式設計式相比更加的直覺,而且突破了計算機架構和計算機語言的限制,通過進階語言編寫的程式,可以通過編譯程式編譯成适用于各種體系結構的計算機語言。進階語言擁有了人類認知語言的特征,遵循某種文法規則,擁有良好的可讀性。

進階語言往往是把一堆程式指令組織到某一個控制結構中,通過函數來實作具體的功能,程式運作時是通過主函數調用一個個函數方法來完成一系列的操作(比如備考,調用讀書,筆記,記憶等函數按照一定順序進行,最後完成備考行為)。

 1、我們寫的程式都要依賴于作業系統運作。

 2、作業系統“規定”了任何程式要想在它肉體上運作必須有個主函數,譬如c++中的main函數

3、主函數既是程式的入口,又是程式的出口

4、否則你以為你寫的程式如果不按照規範來在作業系統的地盤上真能運作?

-----------------掃盲結束>

 (二)漏洞入侵程式

黑客發起攻擊往往是通過漏洞入侵程式。

我們知道程式是遵守某種确定的執行流程的一組複雜規則,這些規則最終告訴計算機應該做什麼,程式理論上想要按照既定規則運作,甚至考慮到了安全因素,但由于設計本身的缺陷或是程式運作環境的不足,程式運作的結果往往達不到預期甚至是不可預計的錯誤。

溫馨舉例:(趙本山獨幕喜劇《捐助》中,趙以為自己按了3000,但是看錯了小數點,導緻捐了三萬出去,程式隻會嚴格按照規則運作,疏忽往往造成非預期的後果)。

多數情況程式員寫出的代碼都不能準确反映他的意圖,如栅欄柱錯誤(要建造100英尺長的栅欄,每10英尺打一根柱子,很多人第一反映是打10根,但正确答案是需要11根),栅欄柱說明設計者搞錯了計算的是資料項而不是資料項間隔,很多時候直覺會給人帶來不可預期的錯誤。

當類似栅欄柱的錯誤相當隐蔽的存在于程式中,如果按照既定規則和輸入進行似乎一切都會很順利,測試也一切正常,但一旦程式接受了非法的輸入,錯誤的結果會影響整個邏輯導緻程式崩潰,在程式受到攻擊時,這種錯誤往往會使一個看似牢不可破的安全程式瞬間崩塌。

舉個openSSH的例子,OpenSSH的設計之初是為了替代不安全的未加密的服務(如telnet,rsh,rcp),理論上它代表着安全的終端通信程式,然而就是這個安全程式中存在着及其典型的栅欄柱錯誤,OpenSSH中有一段代碼包含如下if語句:

if(id<0||id>channels_alloc){……}

正确的應該是:

if(id<0||id>=channels_alloc){……}

(請仔細看兩句話的差別)

設計的初衷是“如果id大于0或者大于等于channels_alloc則執行下面的操作”,然後卻寫成了“如果id大于0或者大于channels_alloc則執行下面的操作”,這個疏忽使程式存在被進一步攻擊的可能,所有普通使用者的認證和登陸都可以獲得系統的全部管理權限。顯然這不符合OpenSSH這種号稱安全程式的初衷,然而計算機隻會忠實執行,即使這并不是設計者的本意。

另外一種常見的安全漏洞常常發生在快速更改以擴充程式功能的場景中。

軟體本身不可不免的會面臨變更更新,然後在帶來功能擴充的同時又加大了程式的複雜度,也就不可避免的增加了風險。

舉個微軟IIS的例子,IIS為使用者提供靜态的和互動的Web内容,為了完成這項功能就不得不允許使用者讀寫并執行特定目錄中的程式和檔案,但是這種功能必須限定在那些特定目錄下。如果沒有加以限制,使用者就可以完全控制系統,從安全角度出發,顯然這是不可接受的。是以程式中就應該設計有路徑檢測代碼,以阻止使用者使用反斜杠字元通過目錄樹反向退回進入其他目錄。

類似程式的漏洞,如IPC$,準确定位這個不應歸于系統漏洞,僅僅是為了友善管理者的維護,然而卻屢屢被黑客利用加以入侵。蠕蟲代碼利用Unicode的轉換漏洞破壞Web頁面(%5c可以轉換成反斜杠,用其避開路徑檢查就可以周遊目錄)。

經過以上的介紹相信大家對漏洞應該有了直覺的認識,希望大家在通讀本文之後能夠思考一下你手頭程式所面臨的安全風險。對應栅欄柱考慮邊界測試,對應功能擴充考慮監控風險。要知道做一個合格的安全程式員,你不應隻局限于寫代碼,更多的精力應關注測試,甚至是代碼管理(變更管理,風險管理等)。

最後給大家留個思考題,思考一下,前一陣特别火的心髒出血和bash漏洞是怎麼産生的。

轉載自: http://www.jtthink.com/2014/11/12/h2.htm

繼續閱讀