Meltdown和Spectre分析以及CPU芯片漏洞攻擊實戰,教你如何破解macOS上的KASLR。html
做者:蒸米,白小龍 @ 阿里移動安全 來源:git
https://paper.seebug.org/497/github
0x00 影響緩存
早上忽然就被Meltdown和Spectre這兩個芯片漏洞刷屏了,但基本上都是一些新聞報道,對漏洞的分析和利用的信息基本爲0。做爲安全研究者,不能只浮在表面,仍是要深刻了解一下漏洞才行,因而開始研究這方面的資料。結果發現其實這個硬件漏洞的影響很是廣,不光是Intel, ARM和AMD也受影響,只是AMD的影響比較小罷了。所以基本上全部的操做系統(Windows,macOS,Linux,Android等)都有被攻擊的風險。漏洞有兩種攻擊模式:一種被稱爲Meltdown,是在用戶態攻擊內核態,形成內核信息泄露。另外一種被稱爲Spectre,一個應用能夠突破本身的沙盒限制,獲取其餘應用的信息。另外,由於是硬件漏洞,這個攻擊對雲的影響很是大,利用這個漏洞,一個guest能夠獲取host或同一臺服務器上其餘guest的信息,能夠說是一個很是嚴重的漏洞,所以亞馬遜和google都在緊急加班修復漏洞。好比google就公佈了漏洞修復的進度在:https://support.google.com/faqs/answer/7622138。雖然是硬件漏洞,可是在系統或軟件層面上經過犧牲性能的方法仍是能夠進行修補的。安全
0x01 緣由服務器
那麼咱們如今知道漏洞很嚴重了,那麼漏洞造成的緣由是什麼呢?關鍵點在於Speculative execution(推測執行)。推測性執行是一種優化技術,CPU會執行一些可能在未來會執行任務。當分支指令發出以後,傳統處理器在未收到正確的反饋信息以前,是不會作任何工做的,而具備預測執行能力的新型處理器,能夠估計即將執行的指令,採用預先計算的方法來加快整個處理過程。若是任務最終沒有被執行,CPU還能夠回滾到以前的狀態,就當作什麼都沒發生過同樣。可是這樣真的安全嗎?答案是,並不安全。攻擊者經過尋找或構建一些指令就能夠在CPU回滾的時間窗口裏進行一系列的攻擊。好比Google Blog中提到的邊界檢查繞過(CVE-2017-5753),分支目標註入(CVE-2017-5715), 惡意數據緩存加載(CVE-2017-5754)。ide
舉個例子,若是CPU執行下面這段代碼:性能
arr1->length沒有被緩存的時候, CPU會從arr1->data[untrusted_offset_from_caller]處讀取數據,若是untrusted_offset_from_caller的值超過arr1->length,就會形成越界讀。固然,正常狀況下這並不會出現什麼問題,由於在執行到判斷語句那一行的時候,CPU發現不對,後面的語句不該該被執行,因而會將狀態回滾到越界讀以前。fetch
可是接下來,問題就出現了。假設arr1->length,arr2->data[0x200]和arr2->data[0x300]都沒有被緩存,CPU會繼續推測執行下面的代碼,在這裏index2會根據value&1產生兩個不一樣的值0x200,0x300,而Value就是越界讀到的值。接下來,代碼會根據Value的值去讀取arr2->data[0x200]或arr2->data[0x300]的值而且這個值會被加入到緩存裏。接下來,咱們能夠再次嘗試去讀取arr2->data[0x200]和arr2->data[0x300],讀取時間短的那個值說明被緩存過了,所以就能夠判斷出value&1的值爲0仍是1,從而作到內核信息泄露。優化
其實,在google的blog發佈以前,就已經存在相似的攻擊了,只是危害沒有這麼大而已,今天咱們就直接實戰一個利用Intel CPU芯片漏洞來破解macOS KASLR的攻擊。
0x02 芯片漏洞實戰之破解KASLR
這種攻擊比較簡單,可是是後面高級攻擊的基礎,所以咱們先從這個攻擊講起。以前咱們講到,爲了讓CPU效率更高,它們依靠推測性執行在任務到來以前就提早執行任務。一樣,數據預取就利用這個思想推測性地先將數據加載到緩存中。Intel的CPU有五個軟件預取指令:prefetcht0,prefetcht1,prefetcht2,prefetchnta和prefetchw。這些指令做用是提示CPU,告訴他一個特定的內存位置可能很快被訪問。然而,Intel的手冊中卻提到,預取「未映射到物理頁面的地址」會致使不肯定的性能損失。所以,咱們能夠經過CPU預讀指令執行的時間長短來判斷這個地址有沒有被映射到物理頁面上。
咱們知道KASLR的原理是在內核的基址上增長一個slide,讓攻擊者沒法猜想內核在內存中的位置。可是內核確定是被映射到物理頁面上的,所以咱們可使用預取指令去遍歷內核可能的起始地址,若是執行預取指令的時間忽然變短,就說明咱們猜中了內核的起始地址。咱們在網上成功找到了破解macOS 10.13 KASLR的POC,並作了一點簡單的修改:https://pastebin.com/GSfJY72J
其中關鍵代碼以下:
這是一段彙編,參數會傳入想要預取的地址,而後利用rdtscp和rdtscp來統計指令執行的時間,並返回。因而咱們從內核可能的起始地址開始,不斷地執行這段彙編代碼,直到咱們找到內核的起始地址爲止。
能夠看到在0x15c00000這一行,指令執行的時間明顯縮短了。所以,咱們能夠猜出Kernel Side爲0x15c00000。
0x03 修復
根據某內部漏洞修復人員在twitter上的回覆,蘋果已經在macOS 10.13.2上對此類芯片漏洞進行了修復,採用了犧牲性能的針對用戶態使用兩次映射的方式來解決該問題。並號稱10.13.3上有更好的解決方案。另外iOS的A*系列芯片暫時還不受這類漏洞的影響。
0x04 總結
本篇文章只是給芯片的一系列漏洞開了個頭,咱們隨後還會有更多關於芯片漏洞的分析和利用實戰,歡迎繼續關注本系列的文章,謝謝。
參考文獻:
1. https://googleprojectzero.blogspot.hk/2018/01/reading-privileged-memory-with-side.html
2. https://siguza.github.io/IOHIDeous/
3. Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR, CCS 2016.