<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          通過幾行 JS 就可以讀取電腦上的所有數(shù)據(jù)?

          共 5889字,需瀏覽 12分鐘

           ·

          2022-03-07 22:28

          Spectre 漏洞究竟有啥魔力,讓瀏覽器頻繁的為它更新策略呢,今天我就來給大家講解一下。

          Spectre

          如果一個漏洞很難構(gòu)造,就算他能夠造成再大的危害,可能也不會引起瀏覽器這么大的重視,那么我們今天的主角 Spectre ,是又容易構(gòu)造,而且造成的危害也很大的,利用  Spectre ,你可以:

          通過幾行 JavaScript ,就可以讀取到電腦/手機上的所有數(shù)據(jù),瀏覽器中的網(wǎng)頁可以讀取你所有的密碼,知道其他程序在干什么,這甚至不需要你寫出來的程序是有漏洞的,因為這是一個計算機硬件層面上的漏洞。

          想要理解 Spectre ,我們需要下面三個方面的知識:

          • 理解什么是旁路攻擊
          • 理解內(nèi)存的工作方式
          • 理解計算機的預(yù)測執(zhí)行

          其實都是一些非常基礎(chǔ)的計算機知識,大家可能學(xué)校里都學(xué)到過的,那么 Spectre 則巧妙利用了上面三個原理,下面我們來挨個看一下。

          大家可以完全不用擔(dān)心,我會用最簡單的方式給大家講明白,先把這些知識拆解一下,最后組合起來其實是很容易理解的。

          內(nèi)存的工作方式

          首先,我們的電腦是由很多零部件構(gòu)成的:

          • 存儲:內(nèi)存、硬盤等等
          • CPU
          • 輸入輸出設(shè)備:鍵盤鼠標(biāo)等

          我們的計算機運行的時候呢,從存儲設(shè)備加載程序進入 CPU,CPU 負(fù)責(zé)處理進行大量運算,這些運算需要內(nèi)存的數(shù)據(jù)進行多次讀取。然后把結(jié)果輸出到我們的顯示器等輸出設(shè)備里面,這大概是是一個計算機簡單的工作原理。

          下面我們把關(guān)注點放到 CPU 和內(nèi)存上面,內(nèi)存里存放著你正在運行的很多程序,包括系統(tǒng)、用戶數(shù)據(jù)等等、同時也存儲了 CPU 運算的中間結(jié)果。

          要存儲這么多信息,需要一個規(guī)范化的存儲方式,我們可以把內(nèi)存想像成一堆排列好的小的內(nèi)存塊,每個內(nèi)存塊里保存著一位信息。

          另外,內(nèi)存是有很多層的,CPU 去里面讀一個數(shù)據(jù)是很慢的,所以我們又在 CPU 和 內(nèi)存中建立了幾級緩存,當(dāng)我們?nèi)〉揭粋€被緩存過的數(shù)據(jù)時,速度會快一點。那當(dāng)訪問一個沒被緩存過的數(shù)據(jù)時,數(shù)據(jù)會在緩存內(nèi)存里創(chuàng)建一個副本,下次再訪問到它就會很快。

          這就是內(nèi)存大概的工作原理,當(dāng)然這個過程簡化了很多,我們在這里只需要簡單理解即可。

          旁路攻擊

          那么啥是旁路(side-channel)呢?

          我們可以簡單這樣理解:假如在你的程序正常的通訊通道之外,產(chǎn)生了一種其他的特征,這些特征反映了你不想產(chǎn)生的信息,這個信息被人拿到了,你就泄密了。這個邊緣特征產(chǎn)生的信息通道,就叫旁路。

          比如你的內(nèi)存在運算的時候,產(chǎn)生了一個電波,這個電波反映了內(nèi)存中的內(nèi)容的,有人用特定的手段收集到這個電波,這就產(chǎn)生了一個旁路了。基于旁路的攻擊,就稱為旁路攻擊。

          常見的旁路還有:時延,異常,能耗,電磁,噪聲,可見光,錯誤消息,頻率,等等,反正你運行總是有邊緣特征的,一不小心這個邊緣特征就成了泄密的機會。

          我們來舉個基于時延來進行旁路攻擊的例子:

          假設(shè)我們想讓電腦驗證一下密碼,比如我們的密碼是 ConardLi。

          下面我們從攻擊者的角度來猜一下,密碼是啥,我們從一個字母開始猜:

          • 密碼是 A,計算機 1ms 后告訴我:不對!
          • 密碼是 B,計算機 1ms 后告訴我:不對!
          • 密碼是 C,計算機 1.1ms 后告訴我:不對!

          有沒有發(fā)現(xiàn)啥問題?我們第一個字母猜對了,但是計算機告訴我們密碼錯誤的時間增加了 0.1ms?

          因為這次,計算機發(fā)現(xiàn)第一位匹配后,需要驗證第二位是否匹配,所以會多花費一些時間。是不是很巧妙!

          我們可以以同樣的方式,再繼續(xù)驗證 Ca、Cb、... Co,最終猜測出我們的密碼。

          這時我們的猜測時間和密碼長度是線性關(guān)系,我們可以再 O(n) 的時間復(fù)雜度內(nèi)猜出密碼。如果直接爆破,我們至少需要進行 52 的 8 次方次計算!

          這就是旁路攻擊,這該死的魅力!

          CPU的預(yù)測執(zhí)行

          上面我們提到,當(dāng)CPU運行的時候,會頻繁的從內(nèi)存中調(diào)取信息。但是讀取內(nèi)存很慢,CPU 為此要花費很長的時間空閑,只為了等待內(nèi)存的數(shù)據(jù)。這顯然不是個很好的方案。

          所以,人們想,是不是 CPU 可以推測一下需要執(zhí)行的命令呢?

          假設(shè)我們有下面這樣的代碼,根據(jù)內(nèi)存中的某個數(shù)據(jù)判斷執(zhí)行不同的語句:

          if(Menory === 0){
            // 進行第一步計算
            // 進行第二步計算
            // 進行第三步計算
          }

          這里有兩種可能,Menory 是 0 或者不是 0 。

          這時 CPU 等待內(nèi)存數(shù)據(jù)時就會預(yù)測,假設(shè)讀取內(nèi)存返回 0,CPU 可以不等待內(nèi)存返回,直接搶跑:跳過 if 判斷直接執(zhí)行里面的計算命令。

          那么如果內(nèi)存真的返回 0 ,CPU 已經(jīng)成功超前運行,CPU 可以繼續(xù)執(zhí)行后面的命令。但是假如內(nèi)存沒有返回 0 ,CPU 就會回滾之前執(zhí)行的結(jié)果。

          所以,CPU 執(zhí)行需要非常小心,不能直接覆蓋寄存器的值,從而真的改變程序的狀態(tài),一旦發(fā)現(xiàn)預(yù)測失敗就立刻回滾改動。

          攻擊的原理

          前面,我們已經(jīng)掌握了這個漏洞利用到的所有因素,下面我們來看看它具體是咋回事。

          假設(shè)下面是我們的緩存,讀取它很慢。系統(tǒng)內(nèi)核將它進行分塊,分配給不同的程序,如果考慮云計算的話,可能分配給不同的虛擬機。

          不同程序可能分配到的內(nèi)存塊是相鄰的,我們繼續(xù)用之前的文章 HTTP 緩存別再亂用了!推薦一個緩存設(shè)置的最佳姿勢! 中的例子:

          紅色的內(nèi)存塊中存儲著我們受害者的數(shù)據(jù),比如受害者的某個密碼:

          操作系統(tǒng)會試圖確保一個程序無法訪問屬于其他程序的內(nèi)存塊,不同程序的內(nèi)存塊會被隔離開。

          所以其他程序無法直接讀取 “受害者”(紅色區(qū)域)的數(shù)據(jù):

          加入我們試圖直接訪問紅色區(qū)域肯定是讀不到的 ,但是緩存中可能已經(jīng)存在一些數(shù)據(jù),下面我們可以試著用高速緩存來搞點事情。

          我們在紫色的內(nèi)存塊放一個數(shù)組 A,這塊內(nèi)存屬于我們的程序,可以合法訪問,但是它很小,只有兩位。

          但是我們不滿足于讀取數(shù)組 A 中的兩個元素,我們試圖超出 A 的范圍(下標(biāo)越界),訪問 A 數(shù)組的第 X 位。但是 X 可能遠(yuǎn)遠(yuǎn)超出 A 數(shù)組的長度。

          通常情況下, CPU 會阻止這一操作,拋出一個錯誤:“非法操作”,然后操作會被強制結(jié)束 ,然而我們可以再試圖觀測這個過程,我們看看是怎么做到的。

          我們在我們允許訪問的內(nèi)存范圍內(nèi)再次新建一個區(qū)域,可以叫工具箱。

          我們特別要求 CPU 對這段數(shù)據(jù)不要拷貝到緩存,只保留于內(nèi)存,這是一段連續(xù)的內(nèi)存區(qū)域。

          假設(shè)我們執(zhí)行的指令長這樣,首先有個 if 判斷語句:

          if(name === 'code秘密花園'){
            // ...
          }

          一般來講,CPU 執(zhí)行會先無視這個判斷,因為它需要等待內(nèi)存返回 name 的值是不是等于 code秘密花園,因為有預(yù)測執(zhí)行這樣的技術(shù),if 語句中的東西會被預(yù)先執(zhí)行。

          if(name === 'code秘密花園'){
            access Tools[A[x]]
          }

          我們嘗試讀取 Tools 的第(A的第X元素)個元素。假如我們讀到的這個受害者內(nèi)存中包含 3:

          這是我們不應(yīng)該讀取到的,但是我們可以通過預(yù)測執(zhí)行做下面的事情:

          CPU 執(zhí)行了這個不應(yīng)該被執(zhí)行的命令后,CPU 認(rèn)為它需要看一下 A[X] 的值是什么,這時 CPU 并未檢查 A[X] 是否已經(jīng)下標(biāo)越界,因為 CPU 認(rèn)為之后內(nèi)核總會驗證下標(biāo)是否越界,如果越界就強制結(jié)束程序。

          于是,預(yù)測執(zhí)行就直接查詢了 A[X] 的值,然后發(fā)現(xiàn) A[X] = 3,也就是:

          Tools[A[x]] = Tools[3]

          也就是我們實際內(nèi)存中 Tools 存儲的第四個元素 a,下面重點來了:

          CPU 訪問到 a 后,將 a(即Tools[3]) 放入了高速緩存!

          最后一步,就是遍歷 Tool 中的每一個元素,我們發(fā)現(xiàn)訪問前幾個元素都有點慢,直到訪問到第 3 個突然很快!因為第 3 個元素 a 在緩存中存儲了一份!

          當(dāng)預(yù)測執(zhí)行發(fā)現(xiàn)錯誤的時候,它就會回滾寄存器的變化,但是不會回滾高速緩存!

          信息就這樣的被泄漏了,因為訪問第 3 個元素所需時間比其他要短!這也就是基于時間的旁路。

          于是,我們知道 “受害者” 在內(nèi)存的這個位置有個 3。

          后面,我們可以把 Tools 這篇區(qū)域搞得更大,你就可以猜出其他更多的數(shù)據(jù)!當(dāng)然,這就是實際去攻擊需要考慮的失去了~

          給Web帶來的影響

          上面的原理我們已經(jīng)分析清楚了,實際上使用 JavaScript 實現(xiàn)這個攻擊非常容易,在 JavaScript 里幾乎所有的邊界檢查都可以被繞過,從而實現(xiàn)任意內(nèi)存邊界讀取。我們可以看看下面這段代碼:

          if(index < array.length){
            index = array[index | 0];
            index = (((index * TABLE_STRIDE) | 0) & (TABLE_BYTES - 1)) | 0;
            localJunk ^= probeTable[index | 0] | 0;
          }

          來自不同站點的多個頁面最終可能會在瀏覽器中共享一個進程。當(dāng)一個人使用 window.open、 或 <a href="..." target="_blank">iframe 打開另一個頁面時,可能會發(fā)生問題,如果一個網(wǎng)站包含特定用戶的敏感數(shù)據(jù),則另一個網(wǎng)站可能會利用這樣的漏洞來讀取該用戶的數(shù)據(jù)。

          上面只是舉了一個簡單的例子,其實實際的攻擊面要比這個廣泛的多,為此瀏覽器出了很多的安全策略來解決這個問題,下面我們來看看:

          瀏覽器策略

          緩存推薦設(shè)置

          上一篇文章講的就是這個 HTTP 緩存別再亂用了!推薦一個緩存設(shè)置的最佳姿勢!

          • 為了防止中間層緩存,建議設(shè)置:Cache-Control: private
          • 建議設(shè)置適當(dāng)?shù)亩壘彺?key:如果我們請求的響應(yīng)是跟請求的 Cookie 相關(guān)的,建議設(shè)置:Vary: Cookie

          這下應(yīng)該更明白為要這倆緩存配置了吧,瀏覽器沒有權(quán)利把緩存干掉,它只能做到最大程度的收緊緩存的寬松程度,增加攻擊的難度。

          禁用高分辨率計時器

          要利用 Spectre,攻擊者需要精確測量從內(nèi)存中讀取某個值所需的時間。所以需要一個可靠且準(zhǔn)確的計時器。

          瀏覽器提供的一個 performance.now() API ,時間精度可以精確到 5 微秒。作為一種緩解措施,所有主要瀏覽器都降低了 performance.now() 的分辨率,這可以提高攻擊的難度。

          獲得高分辨率計時器的另一種方法是使用 SharedArrayBuffer。web worker 使用 Buffer 來增加計數(shù)器。主線程可以使用這個計數(shù)器來實現(xiàn)計時器。瀏覽器就是因為這個原因禁用了 SharedArrayBuffer

          rel="noopener"

          瀏覽器 Context Group 是一組共享相同上下文的 tab、windowiframe 。例如,如果網(wǎng)站(https://a.example)打開彈出窗口(https://b.example),則打開器窗口和彈出窗口共享相同的瀏覽上下文,并且它們可以通過 DOM API 相互訪問,例如 window.opener。

          所以瀏覽器推薦大家在打開不信任的外部頁面時指定 rel="noopener" 。

          跨源開放者策略(COOP)

          利用 Spectre ,攻擊者可以讀取到在統(tǒng)一瀏覽器下任意 Context Group 下的資源。

          COOP:跨源開放者政策,對應(yīng)的 HTTP HeaderCross-Origin-Opener-Policy。

          通過將 COOP 設(shè)置為 Cross-Origin-Opener-Policy: same-origin,可以把從該網(wǎng)站打開的其他不同源的窗口隔離在不同的瀏覽器 Context Group,這樣就創(chuàng)建的資源的隔離環(huán)境。

          詳細(xì)的可以看我這篇文章:新的跨域策略:使用COOP、COEP為瀏覽器創(chuàng)建更安全的環(huán)境

          跨源嵌入程序政策(COEP)

          COEP:跨源嵌入程序政策,對應(yīng)的 HTTP HeaderCross-Origin-Embedder-Policy

          啟用 Cross-Origin-Embedder-Policy: require-corp,你可以讓你的站點僅加載明確標(biāo)記為可共享的跨域資源,或者是同域資源。

          詳細(xì)的也不多介紹了,其實都在這篇文章里講過了:新的跨域策略:使用COOP、COEP為瀏覽器創(chuàng)建更安全的環(huán)境

          跨域讀取阻止(CORB)

          即使所有不同源的頁面都處于自己單獨的進程中,頁面仍然可以合法的請求一些跨站的資源,例如圖片和 JavaScript 腳本,有些惡意網(wǎng)頁可能通過 <img> 元素來加載包含敏感數(shù)據(jù)的 JSON 文件。

          如果沒有 站點隔離 ,則 JSON 文件的內(nèi)容會保存到渲染器進程的內(nèi)存中,此時,渲染器會注意到它不是有效的圖像格式,并且不會渲染圖像。但是,攻擊者隨后可以利用 Spectre 之類的漏洞來潛在地讀取該內(nèi)存塊。

          跨域讀取阻止(CORB)可以根據(jù)其 MIME 類型防止 balance 內(nèi)容進入渲染器進程內(nèi)存中。

          詳細(xì)的原理,可以看這篇文章:跨域,不止CORS

          參考

          • https://www.bilibili.com/video/av18144159/
          • https://zhuanlan.zhihu.com/p/32784852

          最后

          瀏覽器做了這么多的策略,其實只能說可以在一定程度上緩解這個漏洞,實際上并不能從根源上消除,因為本質(zhì)上 Spectre 還是一個硬件層面上的漏洞、提升漏洞的攻擊成本。

          這個漏洞本身也很難解,無論是預(yù)測執(zhí)行還是緩存,做了限制就代表性能會大大降低,所以硬件層面上也一直沒有解決這個問題。

          后續(xù)瀏覽器可能還會出更多的策略或者推薦配置,大家可以持續(xù)關(guān)注~


          點贊在看點這里??

          瀏覽 62
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  十八禁网站免费看 | 日韩欧美一道本 | 一区高清视频 | 3344在线观看免费下载视频 | 黄18禁网站 |