說人話系列:從Intel處理器漏洞談相關冷知識
這次的「Intel處理器漏洞」影響之廣泛可以說是前無古人了。當然,將其稱之為「Intel處理器漏洞」也確實有些冤枉Intel了,畢竟其他處理器也都不同程度的受到了影響,只不過Intel是被影響最嚴重的廠商,但是事件發生後Intel股價單日下跌8%已經證明一切。
其實我一直以來都想找個機會能給各位關注知乎「黑客說」專欄的同學講些系統底層的知識,這次Intel的漏洞算是個不錯的契機。由於「黑客說」的slogen是「安全圈老鳥為小白開放的一塊自留地」,因此我希望能用最簡潔的語言向相對零基礎的朋友描述清楚計算機底層世界中的一些冷知識。
目錄
引子——來自虛擬世界底層的災難
微碼——中央處理器的另一番景色
氮氣——中央處理器加速技術解密
熔毀——摧毀虛擬世界的許可權長城
錫安——屢次被黑客攻破的聖盔谷
結尾——對於底層黑客技術的迷思
引子——來自虛擬世界底層的災難
元旦剛過,第一篇詳細描述此Intel漏洞的可查報道由 John Leyden 與 Chris Williams 於2018-01-02發布在英國老牌技術媒體The Register上,約12小時後Google公司的Project Zero安全團隊在2018-01-03發布了名為《1995年後的幾乎所有CPU都將受到「熔毀」與「幽靈」漏洞的影響》,將此事件推向高潮。
從漏洞分析的蜘絲馬跡來看,此漏洞至少早在2017-12-09以前就已經在業內的部分圈子內開始被有序研究了,那麼這究竟是一個什麼漏洞呢?與CPU又有什麼關係呢?具體能造成什麼後果呢?我們研究它有什麼收益呢?下面我就一一回答這些問題。
首先,概括的說這就是一個由於CPU指令加速功能的設計缺陷,導致的微結構內部通過側信道向外部泄漏數據的一個Bug(不要怕,這種專業解釋看不懂很正常)。而我們這篇文章的主要目的之一就是以淺顯易懂的語言讓各位零基礎讀者理解這究竟是什麼意思。既然提到了CPU指令加速,那麼很顯然就是與CPU相關了,而目前修復這個漏洞的方法自然也是對CPU的指令加速這一機製做了某些限制,打完補丁後會直接導致CPU速度降低30%~35%(嗯,你沒看錯,你的i7瞬間就變i5了,不過沒事,別人的i5也會變成i3的),雖然Intel聲明說根據用戶的不同應用場景,在大多數情況下影響並沒有這麼誇張。但是道理咱們都懂的,雖然原本最快能跑200km/h的性能車打完補丁後就變成了最快只能跑130km/h的麵包車,但是在處處堵車的大背景下我們確實是也很少跑到130km/h,不過問題是我多花的那些錢找誰要去呢?
其次,這個漏洞能造成的後果就目前來看還是相對比較有限的,因為其對關鍵內存區域只有讀許可權沒有寫許可權,所以能夠引起最大的問題就是關鍵數據(例如各位都能夠理解的用戶名、密碼)被泄漏。如果合理的映射到的實際攻擊場景中,效果就是受害者瀏覽一個能夠觸發此漏洞的網頁,然後其瀏覽器中自動保存的那些用戶名、密碼就被瞬間竊取了。當然,深究下去的話,黑客們如果利用此技術補白其在攻擊過程中缺少的關鍵信息,那麼由此導致的後果就不可估量了。目前直接導致的最大問題就是各種雲、各種IDC將面臨關鍵數據泄漏災難,而漏洞補上後又會導致整體性能下降30%,同樣也算是另外一種災難了。
最後,就是研究這個漏洞究竟有什麼收益。其實,這個漏洞中引伸出來的很多知識點都是信息安全領域中比較核心的內容,也有些知識是深入學習軟體逆向所需要掌握的。如果你對信息安全感興趣,那麼這篇科普文你一定要從頭到尾一字不落的讀下來,讀完之後,你眼中的計算機將會是另一番景象。
微碼——中央處理器的另一番景色
有些基礎的同學可能知道程序的最底層就是由「機器碼」構成的,這些「機器碼」是由程序員們通過使用例如C、CPP等計算機語言編寫的源代碼經過編譯器編譯生成的。這些二進位的「機器碼」被以某種方式讓CPU讀取到後執行,就形成了應用程序各種各樣的行為(例如QQ能聊天、Office能辦公、陌陌能把妹等)。
但現實情況並非這麼簡單……
首先,所謂的「機器碼」這個叫法本身並不專業(雖然各大技術論壇的很多文章都這麼寫),其正確的叫法應該是操作碼(OPCode)或勉強算是正確的二進位代碼,因為操作碼是構成計算機指令集體系的一部分(請參考本段後面的「釋義:何為指令集」),所以這並不能被理解為最原子化(不可再分割)的操作。其實,一條操作碼(例如一個加1操作的操作碼是十六進位的0x40,或二進位的1000000,翻譯為彙編就是INC EAX)在被CPU讀取執行時,並非就直接執行了,而是將這條操作碼在CPU內可能會被分解為幾十條至數百條不等的微指令/微碼(MicroCode)再進行運算操作,最後在交由CPU物理層的邏輯電路去執行。
其次,我們平時所能接觸到的一般被稱之為計算機體系結構(Architecture),而CPU中使用的則是微體系結構(Microarchitecture)。這就導致實質上大多數的IT工作者(包括普通程序員乃至彙編語言程序員甚至大部分軟體安全研究員)所接觸的最底層其實就是計算機體系結構這一層(例如我們現在廣泛使用的馮·諾依曼結構,也叫做存儲程序方式結構),在這個結構中,CPU被看作是一個不可被再分割的單元,被看作是一個黑盒子,因為在大多數IT工作者的實際工作過程中,最多也只能涉及到操作碼(二進位代碼)這一級,所以哪怕是在例如信息安全等相對比較專業的領域,有關微體系結構中的微指令這個概念也是鮮有人知的。
最後,關於微體系結構本身,這其實是一個CPU最為核心的部分,對於大多數IT工作者而言,CPU微結構並不暴露給他們,哪怕是最底層的軟體安全研究員也只能是通過操作碼來訪問CPU,因此就目前層面而言我們能使用CPU的最小操作粒度就是指令了。但我們上面也簡單的說過,操作碼在被CPU讀取後還可能會被解析成為若干條更小的執行單元,並由這些單元最終驅動CPU的單個硬體邏輯電路去完成具體計算操作,而這些更小的執行單元就被稱之為微操作(MicroOP/μOP)或者微指令/微碼(MicroCode)。在實際應用場景中,微指令是可以完成一些非常複雜的操作的,而通過修改CPU的微指令在很多時候甚至可以幫助廠商協助用戶修補已經發售CPU的Bug(可惜這次漏洞由於過於複雜,不能通過修改微指令修復此漏洞)。
釋義:何為指令集
指令集是指CPU提供給外界的功能介面,舉例來說,空調的指令集就包含「開關機」、「調高溫度」與「調低溫度」等,而空調提供給我們的指令集介面,就是空調遙控器。
而CPU的指令集是由彙編語法、OPCode等構成,彙編語言是OPCode的一種文字化映射,可以將看似毫無含義且晦澀難讀的二進位代碼一一對應為用英文單片語成的彙編語言,以方便人們使用。
這類似於空調遙控器將人類完全無法看見的紅外信號影射為遙控器上的一個個按鈕,這樣人們只需要操作按鈕就可以由遙控器轉化為紅外信號指揮空調操作。
因此,我們可以將操作碼(OPCode)類比為空調用於通信的紅外信號。
氮氣——中央處理器加速技術解密
氮氣,作為超級跑車在賽道上扭轉乾坤的利器,可以將引擎的最後一點潛能完全壓榨出來,以此獲得爆裂般的加速。而CPU作為對速度有更高要求的計算機核心部件,對於速度的追求自然是用戶以及工程師們的終極夢想,因此各個實驗室的工程師們也必將為此絞盡腦汁……
本段我們就以Intel CPU的發展為例為各位同學簡要闡述一下CPU中的「氮氣」加速技術是怎麼一點點被開發出來的。
原始級,蠻荒狀態-1987年
Intel在1978-06-08創造了8086處理器,這時處理器的執行流程非常簡單,就是從內存中讀取操作碼後將操作碼解碼解析成微指令,並由微指令驅動邏輯電路去完成具體計算操作,然後再讀取下一條指令。
以上操作可被概括為取指令、解碼和執行這三步,而且每次都要等到這三個步驟都完成後才能執行下一條指令。
上古級,指令緩存-1982年
由於CPU的執行速度遠高於內存的讀取速度,因此Intel發現整個CPU的性能瓶頸出現在內存讀取這一環節上。而又因為絕大多數指令編譯的操作碼僅幾個位元組大小,所以Intel在1982年發布了一款新CPU 80186,並且增加了指令緩存機制。
80186擁有一個6位元組的指令緩存器,在每次剩餘空間大於等於3位元組時,80186就會自動提前將下一條指令從內存中讀取進來,進而大大降低了操作碼的讀取延遲。
古代級,數據緩存-1985年
由於指令緩存機制在80186上取得了巨大成功,因此Intel在1985年發布的80386上面將指令緩存提高到了最大8KB,相較80186增加了1300餘倍,並增加了數據緩存機制。
除此之外,Intel為了進一步降低因內存讀取而造成的高延時,還為80386增加了最高64KB的數據緩存,使得80386有能力預先將一部分數據從內存讀取到CPU的數據緩存區域,從而極大的降低因為CPU需要頻繁訪問內存而造成的延遲,例如:
int nArray[100] = {1,2,3,4,5,6,7,8,9,10, ... };nfor (int i=0; i<100; i++)n printf("%02d ", nArray[i]); // 重複訪問100次數組nArrayn
以上這段代碼編譯運行後,我們會發現訪問數組的速度特別快,其主要原因就是數據緩存起到的作用。應用程序以為它是在訪問物理內存中的一塊棧空間的內容,而實際上它是在訪問CPU的數據緩存。
近代級,多流水線-1989年
由於內存的延遲已經被Intel在80386上儘可能的優化,因此Intel的工程師們這一次將優化的目光鎖定在指令執行的流程上,他們首先將指令的執行細分為五個步驟,分別為:
Step1:取指令,將操作碼從指令緩存中取出;
Step2:解碼,將操作嗎翻譯為具體的微指令;
Step3:轉址,將內存地址和偏移進行轉換;
Step4:執行,指令在該階段真正執行運算(由微指令控制硬體邏輯電路去完成);
Step5:退出,將執行結果寫回到寄存器或者內存。
一個指令必須要經過這5步才能執行完成,而CPU執行這5步所需要佔用的CPU時間就被稱之為這條指令執行所需的時鐘周期,需要時鐘周期越短的指令,其在一秒鐘內可以執行的次數就越多,效率就越高。
而Intel工程師之所以將一條指令的執行分為以上5個步驟,就是因為在絕大多數情況下以上五步可以被並行執行。也就是說第一條指令在Step4處執行時,第二條指令可以在Step3執行,而第三條指令則可能在Step2中被執行,這樣每一步都像是一條流水線上的工人,而分為5步就可以被看作一個指令被5個工人分別處理,因此理論上來講,在同一時間內,這條擁有5個工人的五級流水線可以同時並行執行5條指令,而需要佔用的CPU時間相對於以前執行一條指令來說並未因此有太大的增加,具體如下圖所示。
Intel在1989年第一次將五級流水線技術應用到了80486處理器中,使得新處理器在頻率僅為上代一倍多的情況下獲得了數倍於上代CPU的理論執行速度。
現代級,超流水線-1993年
既然流水線這麼強悍,那麼為什麼不多搞一些呢?其實Intel的工程師們也是這麼想的,因此Intel在1993年推出的首代奔騰(因為586這個代號被佔用,所以啟用了新名字Pentium)處理器時,第一次將超標量流水線結構應用到自己的產品中。
新款奔騰處理器的超標量流水線由兩條五級流水線構成,但是限於一些底層邏輯限制,第二條流水線能夠執行的指令類別有所受限,並且在遇到類似於JMP、CALL等轉移指令時會使得第二條流水線失效,但是即便如此,啟用超流水線結構的CPU也比其他同等工況下快了近1倍。
次代級,亂序執行-1995年
通過流水線的優化讓Intel的工程師們嘗到了甜頭,但是因為程序代碼的前後順序邏輯等問題,在增加過多的流水線對於指令的執行速度不會再有明顯的提高,因此Intel的工程師們將優化目標錨定在流水線本身邏輯的修改及加強上。
通過了解多級流水線可知,如果執行指令時各環節工況基本一致,那麼越靠後處理的操作碼所需的絕對執行時間就越長。那麼能否將解碼時間長但執行時間短,和一條解碼時間短但執行時間長的指令合併為前後兩條進行執行呢,因為這樣就可以極大的利用好流水線中的每一級,如下圖所示。
Intel在1995年推出的奔騰Pro處理器中首次應用了可以極大改進流水線工作效率的亂序執行(Out-of-Order, OOO)技術,並且為了緩解因JMP、JNZ等轉移指令對超標量流水線的影響而推出了指令預測(猜測執行/分支預測)技術,這兩種技術的出現使得Intel的流水線已經被優化到了極致。除此之外,奔騰Pro更是將原先的五級流水線升級到了12級,這使得奔騰Pro處理器中的每條流水線理論上可同時執行12條指令。
經過如此優化的流水線已經明顯不符合當時的主流情況,進而導致奔騰Pro上的流水線在大多數情況下實際是在等待新指令的傳入,而正是由於Intel這次跨時代的流水線優化,使其早在23年前便為今天的漏洞埋下了禍根,並且使其養成了擠牙膏的壞習慣,看來車開的太快果然容易出問題。
後現代級,超線程-2002年
由於上次亂序執行與指令預測的雙劍合璧,使得CPU處理指令的速度飆漲,進而導致指令被執行的速度比處理器能夠提供指令的速度更快,因此CPU的超標量流水線部件在大部分時間處於空閑狀態。為了讓整套流水線部件能夠完全發揮其應有的作用,Intel在2002年為奔騰4處理器加入了第二套前端部件(例如寄存器、解碼器等),這樣對於操作系統來說,它就能看到兩個處理器了。這樣來自兩套前端部件的所有的指令被一個共享的流水線部件執行,進而充分的發揮了其本來作用,而這種技術就被稱之為超線程。
熔毀——摧毀虛擬世界的許可權長城
計算機許可權的核心基礎就是將內存賦予了不同的許可權屬性,例如運行於用戶層(RING3,3層)的代碼是不能訪問內核層(RING0,0層)的,如果不是這樣,那麼任意一個用戶層程序都可以通過修改內核層的數據間接控制操作系統,進而隨意控制整個許可權控制系統。由此可見,內存的邊界如果不存在了,其後果是多麼可怕。
而通過我們上一節「次代級,亂序執行-1995年」這部分的分享可知,Intel在1995年開掛一樣為他的CPU增加了兩個新功能,分別為亂序執行與指令預測,而正是由於這兩項開掛般的流水線優化功能導致了這個開掛般的漏洞。
首先,Intel為了使得亂序執行能夠發揮全部效能,因此為了避免性能損失,在其將內存數據讀入到數據緩存時並沒有做任何許可權檢查。這點其實是沒有問題的,因為數據所在的內存屬於計算機體系結構,而讀入的數據緩存則屬於微體系結構,只要CPU在返回處理結果之前(例如將處理結果寫入外部可訪問的寄存器或內存)沒忘記做許可權檢查即可。而實際Intel的CPU也是這麼做的,其CPU內部的緩存無法被CPU之外的任何外部代碼讀取(包括內核態代碼與用戶態代碼),並且在將外部數據讀入到緩存中時也不做任何許可權檢查,而是在將處理結果寫回到外部內存或寄存器之前才會做許可權檢查(但這時某些數據已經被讀入到緩存中了)。
除此之外,Intel的指令預測功能的邏輯也非常簡單,它判斷的就是上一次執行這個條件跳轉時是跳向了哪裡,那麼這次它就認為仍然會跳向那裡。不要看它邏輯簡單,但是卻非常實用,因為CPU執行的絕大多數操作都是循環,而循環的特點是每次執行的代碼其實都是一樣的,僅僅是處理的數據每次有些許差別,所以Intel的這個指令預測的命中率據說可以達到80% 。
其次,既然Intel做數據緩存時沒做許可權檢查,而且指令預測功能又這麼簡單,那麼我們可以不可搞點事情呢?讓我們一起來想想以下場景……
我們通過循環執行某寫代碼而使得CPU的指令預測認為我們下次仍然要執行某指令,而實際在某一次之後其內部的執行細節已經發生改變,原本不會出錯的倒數第二條指令執行後將會出錯,原本正常讀取數據的倒數第一條指令在最後一次則試圖讀取的是內核內存。
這樣,根據CPU的流水線以及數據緩存機制,CPU在執行倒數第二條即將出現錯誤的指令之前就已經將其後面的倒數第一條要讀取內核內存的指令準備妥帖了,也就是說,最後一條指令想要讀取的內核內存數據此時已經被CPU預先載入到其緩存中,並且沒有做許可權檢查。
而由於CPU在執行倒數第二條指令時就會出錯,因此根本就不會再試圖執行倒數第一條指令,但是這時CPU的數據緩存中卻保存著未經許可權檢查而在內核內存中讀取出來的數據。但是由於CPU的數據緩存是外部不可讀取的,因此事情如果僅僅到這一步的話是沒有任何問題的。
最後,因為CPU所有載入到緩存中的數據都可以在用戶層通過一個內存地址訪問,因此黑客們這時可以遍歷一下所有可能對應的內存塊,利用內存訪問與緩存訪問的速度差異可以判斷哪個內存塊是在緩存中的,而非法讀取的內核數據是有意與內存塊對應的,因此原本在用戶模式下不能訪問的內核數據就被推算出來,這就構成了一次側信道攻擊(Side Channel Attack, SCA)。
此次處理器漏洞主要是由以下三個漏洞組合而成的:
CVE-2017-5754(別名熔毀「Meltdown」):惡意的數據緩存載入漏洞
CVE-2017-5753 (別名幽靈一號「Spectre Variant 1」):繞過邊界檢查漏洞
CVE-2017-5715(別名幽靈二號「Spectre Variant 2」):分支目標註入漏洞
錫安——屢次被黑客攻破的聖盔谷
錫安,作為《黑客帝國》中人類的最後一個核心基地,聖盔谷,作為《魔戒》中東土世界中最為堅固的堡壘,被分別用以指代Intel CPU本身以及其堅固的防禦系統實在是再恰當不過了。
然而越是重要價值越大,引起的後果就越嚴重,下面我就為各位讀者羅列一下CPU的Bug史:
1994年:奔騰處理器被爆FDIV Bug,導致的直接結果就是帶小數的除法會被算錯;
2000年:奔騰3的「礦渣」Bug,Intel為了與AMD抗衡通過默認加電壓超頻的方式進行,帶來了巨大的穩定性問題,最後Intel回收了這部分CPU,並將其做成了鑰匙扣;
2004年:奔騰4的90nm工藝漏電Bug,使得CPU巨熱無比只能降頻使用,Intel從此不再談奔騰4架構是為了10GHz做準備的豪言壯語;
2007年:AMD翼龍處理器的TLB Bug,會使得物理內存與虛擬內存的映射表丟失,進而導致死機;
2011年:AMD推土機結構重構了x86架構設計,採用的長管線設計使得其能耗飆升,造成了高頻低能的奇觀;
2015年:Intel Broadwell架構因SpeedStep引發的BDM101/BDM86錯誤,導致在開啟SpeedStep的電腦上運行密集運算程序是會導致系統藍屏死機;
2018年:涉及多家處理器的熔毀漏洞與幽靈漏洞;
2021年:當年5月,讓我們靜靜等待下個漏洞的到來,看看我預測的準不準。
結尾——對於底層黑客技術的迷思
隨著信息時代的逐漸深入,人類社會對於電子化設備的依賴越發嚴重,每過一年都會有更多的寶貴的信息存儲在電子設備中,因此電子設備中所蘊含的價值也在以幾何倍數增加,人類社會勢必會將越來越多的資源傾斜到保護信息安全的工作中去。
由於電子化產品天生易於複製傳播的特點,隨著人類社會整體防禦水平逐步提高,原本很多並沒有很高防禦水平的節點會隨著設備及系統的更新被動的獲得最先進的防禦。這會直接導致信息安全領域的後來者學習門檻逐漸提高,進而篩選出更加優秀的人進入行業內部,反過來在推動整個行業的發展。
此次處理器漏洞就是一個很好的例證,雖然這次攻擊的實施以及攻擊原理本身都不複雜,但這是一次深入到處理結構內部的攻擊,發現這個漏洞的人勢必對於晶元設計以及微體系結構有比較深入了解,同時又具備深厚的信息安全素養。隨著人類社會信息安全產業的逐步發展,這種底層跨界組合的人才將會持續給我們帶來更多驚喜。
因此,這次處理器漏洞帶給我最大的啟發就是——跨界發展,跨界攻擊將成為趨勢。
附錄1-參考資料:
[1] 安天針對處理器A級漏洞Meltdown(熔毀)和Spectre(幽靈)分析報告
[2] Kernel-memory-leaking Intel processor design flaw forces Linux, Windows redesign
[3] Google: Almost All CPUs Since 1995 Vulnerable To &amp;amp;quot;Meltdown&amp;amp;quot; And &amp;amp;quot;Spectre&amp;amp;quot; Flaws
[4] Meltdown and Spectre
[5] Multiple CPUs - &amp;amp;#x27;Spectre&amp;amp;#x27; Information Disclosure (PoC)
[6] CVE - CVE-2017-5754
[7] CVE - CVE-2017-5753
[8] CVE - CVE-2017-5715
附錄2-關於十五派:
十五派(15PB)是一個依託於卓越的研發團隊和豐富的集訓管理經驗,為個人、公司、高校提供定製化信息安全技術教育解決方案的專業團隊,十五派(15PB)隸屬於北京藍森科技有限公司旗下,是國內第一個信息安全教育品牌。
推薦閱讀: