Web 開發(fā)的浩瀚海洋中,CSS 猶如點(diǎn)睛之筆,為網(wǎng)頁增光添彩。而引入 CSS 樣式的方式,也決定了網(wǎng)頁渲染的效率和代碼的可維護(hù)性。 link 和 @import 作為兩種常見的 CSS 引入方式,今天就來一場正面對決,看看誰才是你的最佳選擇!
<!DOCTYPE html>
<html>
<head>
<title>link vs @import</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello world</h1>
</body>
</html>
/* style.css */
@import url("other-style.css");
在瀏覽器解析 HTML 文件時,會依次解析 link 標(biāo)簽和 style 標(biāo)簽,并下載相應(yīng)的 CSS 文件。@import 規(guī)則會在 CSS 文件解析時被執(zhí)行,瀏覽器會再次發(fā)送請求下載 other-style.css 文件。
綜上所述,link 標(biāo)簽憑借其加載速度快、兼容性好、可控性強(qiáng)等優(yōu)勢,在 CSS 引入方式的較量中更勝一籌,是大多數(shù)場景下的最佳選擇。
當(dāng)然,@import 也并非一無是處,在某些特殊情況下,它也能發(fā)揮作用。例如,當(dāng)我們需要根據(jù)不同的條件加載不同的樣式表時,可以使用 @import 結(jié)合 JavaScript 實現(xiàn)動態(tài)加載。
#頭條創(chuàng)作挑戰(zhàn)賽#
<!DOCTYPE>聲明位于位于HTML文檔中的第一行,處于 <html>標(biāo)簽之前。告知瀏覽器的解析器,用什么文檔標(biāo)準(zhǔn)解析這個文檔。DOCTYPE不存在或格式不正確會導(dǎo)致文檔以兼容模式呈現(xiàn)。
標(biāo)準(zhǔn)模式的排版 和JS運(yùn)作模式都是以該瀏覽器支持的最高標(biāo)準(zhǔn)運(yùn)行。在兼容模式中,頁面以寬松的向后兼容的方式顯示,模擬老式瀏覽器的行為以防止站點(diǎn)無法工作。
HTML5 不基于 SGML,因此不需要對DTD進(jìn)行引用,但是需要doctype來規(guī)范瀏覽器的行為(讓瀏覽器按照它們應(yīng)該的方式來運(yùn)行);
而HTML4.01基于SGML,所以需要對DTD進(jìn)行引用,才能告知瀏覽器文檔所使用的文檔類型。**
首先:CSS規(guī)范規(guī)定,每個元素都有display屬性,確定該元素的類型,每個元素都有默認(rèn)的display值,如div的display默認(rèn)值為“block”,則為“塊級”元素;span默認(rèn)display屬性值為“inline”,是“行內(nèi)”元素。
(1)行內(nèi)元素有:a b span img input select strong(強(qiáng)調(diào)的語氣)
(2)塊級元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
(3)常見的空元素:
<img><input><link><meta>
鮮為人知的是:
<area><base><col><command><embed><keygen><param><source><track><wbr>
4.頁面導(dǎo)入樣式時,使用link和@import有什么區(qū)別?
link屬于XHTML標(biāo)簽,除了加載CSS外,還能用于定義RSS, 定義rel連接屬性等作用;而@import是CSS提供的,只能用于加載CSS;
頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載;
import是CSS2.1 提出的,只在IE5以上才能被識別,而link是XHTML標(biāo)簽,無兼容問題;
主要分成兩部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:負(fù)責(zé)取得網(wǎng)頁的內(nèi)容(HTML、XML、圖像等等)、整理訊息(例如加入CSS等),以及計算網(wǎng)頁的顯示方式,然后會輸出至顯示器或打印機(jī)。瀏覽器的內(nèi)核的不同對于網(wǎng)頁的語法解釋會有不同,所以渲染的效果也不相同。所有網(wǎng)頁瀏覽器、電子郵件客戶端以及其它需要編輯、顯示網(wǎng)絡(luò)內(nèi)容的應(yīng)用程序都需要內(nèi)核。
JS引擎則:解析和執(zhí)行javascript來實現(xiàn)網(wǎng)頁的動態(tài)效果。
最開始渲染引擎和JS引擎并沒有區(qū)分的很明確,后來JS引擎越來越獨(dú)立,內(nèi)核就傾向于只指渲染引擎。
Trident內(nèi)核:IE,MaxThon,TT,The World,360,搜狗瀏覽器等。[又稱MSHTML]
Gecko內(nèi)核:Netscape6及以上版本,F(xiàn)F,MozillaSuite/SeaMonkey等
Presto內(nèi)核:Opera7及以上。 [Opera內(nèi)核原為:Presto,現(xiàn)為:Blink;]
Webkit內(nèi)核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]
移除的元素:
純表現(xiàn)的元素:basefont,big,center,font, s,strike,tt,u;
對可用性產(chǎn)生負(fù)面影響的元素:frame,frameset,noframes;
用正確的標(biāo)簽做正確的事情。
html語義化讓頁面的內(nèi)容結(jié)構(gòu)化,結(jié)構(gòu)更清晰,便于對瀏覽器、搜索引擎解析;
即使在沒有樣式CSS情況下也以一種文檔格式顯示,并且是容易閱讀的;
搜索引擎的爬蟲也依賴于HTML標(biāo)記來確定上下文和各個關(guān)鍵字的權(quán)重,利于SEO;
使閱讀源代碼的人對網(wǎng)站更容易將網(wǎng)站分塊,便于閱讀維護(hù)理解。
在用戶沒有連網(wǎng)時,可以正常訪問站點(diǎn)或應(yīng)用,在用戶與網(wǎng)絡(luò)連接時更新用戶機(jī)器上的緩存文件。
原理:HTML5的離線存儲是基于一個新建的.appcache文件的緩存機(jī)制(不是存儲技術(shù)),通過這個文件上的解析清單離線存儲資源,這些資源就會像cookie一樣被存儲了下來。之后當(dāng)網(wǎng)絡(luò)在處于離線狀態(tài)下時,瀏覽器會通過被離線存儲的數(shù)據(jù)進(jìn)行頁面展示。
如何使用:
頁面頭部像下面一樣加入一個manifest的屬性;
在cache.manifest文件的編寫離線存儲的資源;
CACHE MANIFEST
#v0.11
CACHE:
js/app.js
css/style.css
NETWORK:
resourse/logo.png
FALLBACK:
/ /offline.html
在離線狀態(tài)時,操作window.applicationCache進(jìn)行需求實現(xiàn)。
在線的情況下,瀏覽器發(fā)現(xiàn)html頭部有manifest屬性,它會請求manifest文件,如果是第一次訪問app,那么瀏覽器就會根據(jù)manifest文件的內(nèi)容下載相應(yīng)的資源并且進(jìn)行離線存儲。如果已經(jīng)訪問過app并且資源已經(jīng)離線存儲了,那么瀏覽器就會使用離線的資源加載頁面,然后瀏覽器會對比新的manifest文件與舊的manifest文件,如果文件沒有發(fā)生改變,就不做任何操作,如果文件改變了,那么就會重新下載文件中的資源并進(jìn)行離線存儲。
離線的情況下,瀏覽器就直接使用離線存儲的資源。
iframe會阻塞主頁面的Onload事件;
搜索引擎的檢索程序無法解讀這種頁面,不利于SEO;
iframe和主頁面共享連接池,而瀏覽器對相同域的連接有限制,所以會影響頁面的并行加載。
使用iframe之前需要考慮這兩個缺點(diǎn)。如果需要使用iframe,最好是通過javascript
動態(tài)給iframe添加src屬性值,這樣可以繞開以上兩個問題。
label標(biāo)簽來定義表單控制間的關(guān)系,當(dāng)用戶選擇該標(biāo)簽時,瀏覽器會自動將焦點(diǎn)轉(zhuǎn)到和標(biāo)簽相關(guān)的表單控件上。
<label for="Name">Number:</label>
<input type=“text“name="Name" id="Name"/>
<label>Date:<input type="text" name="B"/></label>
WebSocket、也可以調(diào)用localstorge、cookies等本地存儲方式,還可以使用頁面的路有參數(shù)傳遞
localstorge另一個瀏覽上下文里被添加、修改或刪除時,它都會觸發(fā)一個事件,
我們通過監(jiān)聽事件,控制它的值來進(jìn)行頁面信息通信;
14.如何在頁面上實現(xiàn)一個圓形的可點(diǎn)擊區(qū)域?
map+area或者svg
border-radius
純js實現(xiàn) 需要求一個點(diǎn)在不在圓上簡單算法、獲取鼠標(biāo)坐標(biāo)等等
title屬性沒有明確意義只表示是個標(biāo)題,H1則表示層次明確的標(biāo)題,對頁面信息的抓取也有很大的影響;
strong是標(biāo)明重點(diǎn)內(nèi)容,有語氣加強(qiáng)的含義,使用閱讀設(shè)備閱讀網(wǎng)絡(luò)時:會重讀,而是展示強(qiáng)調(diào)內(nèi)容。
i內(nèi)容展示為斜體,em表示強(qiáng)調(diào)的文本;
h5新增的屬性
可以通過ele.dataset獲取到標(biāo)簽上的data-x的屬性
返回一個對象
解決:解決方案是做成PNG8.
解決:方案是加一個全局的*{margin:0;padding:0;}來統(tǒng)一。
解決:解決方案是在float的標(biāo)簽樣式控制中加入 ——_display:inline;將其轉(zhuǎn)化為行內(nèi)屬性。(_這個符號只有ie6會識別)
漸進(jìn)識別的方式,從總體中逐漸排除局部。
首先,巧妙的使用“9”這一標(biāo)記,將IE游覽器從所有情況中分離出來。 接著,再次使用“+”將IE8和IE7、IE6分離開來,這樣IE8已經(jīng)獨(dú)立識別。
css
.bb{
background-color:#f1ee18;/*所有識別*/
.background-color:#00deff\9; /*IE6、7、8識別*/
+background-color:#a200ff;/*IE6、7識別*/
_background-color:#1e0bd1;/*IE6識別*/
}
解決:解決方法:統(tǒng)一通過getAttribute()獲取自定義屬性.
解決方法:(條件注釋)缺點(diǎn)是在IE瀏覽器下可能會增加額外的HTTP請求數(shù)。
解決:可通過加入 CSS 屬性 -webkit-text-size-adjust: none; 解決.
解決:方法是改變CSS屬性的排列順序:L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}
該標(biāo)簽可聲明三種 DTD 類型,分別表示嚴(yán)格版本、過渡版本以及基于框架的 HTML 文檔。
HTML 4.01 規(guī)定了三種文檔類型:Strict、Transitional 以及 Frameset。
XHTML 1.0 規(guī)定了三種 XML 文檔類型:Strict、Transitional 以及 Frameset。
Standards (標(biāo)準(zhǔn))模式(也就是嚴(yán)格呈現(xiàn)模式)用于呈現(xiàn)遵循最新標(biāo)準(zhǔn)的網(wǎng)頁,而 Quirks(包容)模式(也就是松散呈現(xiàn)模式或者兼容模式)用于呈現(xiàn)為傳統(tǒng)瀏覽器而設(shè)計的網(wǎng)頁。
1)所有的標(biāo)記都必須要有一個相應(yīng)的結(jié)束標(biāo)記
2)所有標(biāo)簽的元素和屬性的名字都必須使用小寫
3)所有的XML標(biāo)記都必須合理嵌套
4)所有的屬性必須用引號""括起來
5)把所有<和&特殊符號用編碼表示
6)給所有屬性賦一個值
7)不要在注釋內(nèi)容中使“--”
8)圖片必須有說明文字
title是global attributes之一,用于為元素提供附加的advisory information。通常當(dāng)鼠標(biāo)滑動到元素上的時候顯示。
alt是<img>的特有屬性,是圖片內(nèi)容的等價描述,用于圖片無法加載時顯示、讀屏器閱讀圖片。可提圖片高可訪問性,除了純裝飾圖片外都必須設(shè)置有意義的值,搜索引擎會重點(diǎn)分析。
改版的時候更方便 只要改css文件。
頁面加載速度更快、結(jié)構(gòu)化清晰、頁面顯示簡潔。
表現(xiàn)與結(jié)構(gòu)相分離。
易于優(yōu)化(seo)搜索引擎更友好,排名更容易靠前。
派生選擇器(用HTML標(biāo)簽申明)
id選擇器(用DOM的ID申明)
類選擇器(用一個樣式類名申明)
屬性選擇器(用DOM的屬性申明,屬于CSS2,IE6不支持,不常用,不知道就算了)
除了前3種基本選擇器,還有一些擴(kuò)展選擇器,包括
后代選擇器(利用空格間隔,比如div .a{ })
群組選擇器(利用逗號間隔,比如p,div,#a{ })
那么問題來了,CSS選擇器的優(yōu)先級是怎么樣定義的?
一般而言,選擇器越特殊,它的優(yōu)先級越高。也就是選擇器指向的越準(zhǔn)確,它的優(yōu)先級就越高。
復(fù)雜的計算方法:
用1表示派生選擇器的優(yōu)先級
用10表示類選擇器的優(yōu)先級
用100標(biāo)示ID選擇器的優(yōu)先級
div.test1 .span var 優(yōu)先級 1+10 +10 +1
span#xxx .songs li 優(yōu)先級1+100 + 10 + 1
xxx li 優(yōu)先級 100 +1
那么問題來了,看下列代碼,<p>標(biāo)簽內(nèi)的文字是什么顏色的?
<style>
.classA{ color:blue;}
.classB{ color:red;}
</style>
<body>
<p class='classB classA'> 123 </p>
</body>
答案:red。與樣式定義在文件中的先后順序有關(guān),即是后面的覆蓋前面的,與在<p class=’classB classA’>中的先后關(guān)系無關(guān)。
塊級元素(block)特性:
總是獨(dú)占一行,表現(xiàn)為另起一行開始,而且其后的元素也必須另起一行顯示;
寬度(width)、高度(height)、內(nèi)邊距(padding)和外邊距(margin)都可控制;
內(nèi)聯(lián)元素(inline)特性:
和相鄰的內(nèi)聯(lián)元素在同一行;
寬度(width)、高度(height)、內(nèi)邊距的top/bottom(padding-top/padding-bottom)和外邊距的top/bottom(margin-top/margin-bottom)都不可改變(也就是padding和margin的left和right是可以設(shè)置的),就是里面文字或圖片的大小。
那么問題來了,瀏覽器還有默認(rèn)的天生inline-block元素(擁有內(nèi)在尺寸,可設(shè)置高寬,但不會自動換行),有哪些?
答案:<input> 、<img> 、<button> 、<texterea> 、<label>。
外邊距重疊就是margin-collapse。
在CSS當(dāng)中,相鄰的兩個盒子(可能是兄弟關(guān)系也可能是祖先關(guān)系)的外邊距可以結(jié)合成一個單獨(dú)的外邊距。這種合并外邊距的方式被稱為折疊,并且因而所結(jié)合成的外邊距稱為折疊外邊距。
折疊結(jié)果遵循下列計算規(guī)則:
兩個相鄰的外邊距都是正數(shù)時,折疊結(jié)果是它們兩者之間較大的值。
兩個相鄰的外邊距都是負(fù)數(shù)時,折疊結(jié)果是兩者絕對值的較大值。
兩個外邊距一正一負(fù)時,折疊結(jié)果是兩者的相加的和。
rgba()和opacity都能實現(xiàn)透明效果,但最大的不同是opacity作用于元素,以及元素內(nèi)的所有內(nèi)容的透明度,
而rgba()只作用于元素的顏色或其背景色。(設(shè)置rgba透明的元素的子元素不會繼承透明效果!)
* 1.id選擇器( # myid)
2.類選擇器(.myclassname)
3.標(biāo)簽選擇器(div, h1, p)
4.相鄰選擇器(h1 + p)
5.子選擇器(ul < li)
6.后代選擇器(li a)
7.通配符選擇器( * )
8.屬性選擇器(a[rel = "external"])
9.偽類選擇器(a: hover, li: nth - child)
* 可繼承: font-size font-family color, UL LI DL DD DT;
* 不可繼承 :border padding margin width height ;
* 優(yōu)先級就近原則,樣式定義最近者為準(zhǔn);
* 載入樣式以最后載入的定位為準(zhǔn);
優(yōu)先級為:
!important > id > class > tag
important 比 內(nèi)聯(lián)優(yōu)先級高
CSS3新增偽類舉例:
p:first-of-type 選擇屬于其父元素的首個 <p> 元素的每個 <p> 元素。
p:last-of-type 選擇屬于其父元素的最后 <p> 元素的每個 <p> 元素。
p:only-of-type 選擇屬于其父元素唯一的 <p> 元素的每個 <p> 元素。
p:only-child 選擇屬于其父元素的唯一子元素的每個 <p> 元素。
p:nth-child(2) 選擇屬于其父元素的第二個子元素的每個 <p> 元素。
:enabled、:disabled 控制表單控件的禁用狀態(tài)。
:checked,單選框或復(fù)選框被選中。
給div設(shè)置一個寬度,然后添加margin:0 auto屬性
div{
width:200px;
margin:0 auto;
}
居中一個浮動元素
確定容器的寬高 寬500 高 300 的層
設(shè)置層的外邊距
.div {
Width:500px ; height:300px;//高度可以不設(shè)
Margin: -150px 0 0 -250px;
position:relative;相對定位
background-color:pink;//方便看效果
left:50%;
top:50%;
}
* IE瀏覽器的內(nèi)核Trident、 Mozilla的Gecko、google的WebKit、Opera內(nèi)核Presto;
* png24為的圖片在iE6瀏覽器上出現(xiàn)背景,解決方案是做成PNG8.
* 瀏覽器默認(rèn)的margin和padding不同。解決方案是加一個全局的*{margin:0;padding:0;}來統(tǒng)一。
* IE6雙邊距bug:塊屬性標(biāo)簽float后,又有橫行的margin情況下,在ie6顯示margin比設(shè)置的大。
浮動ie產(chǎn)生的雙倍距離 #box{ float:left; width:10px; margin:0 0 0 100px;}
這種情況之下IE會產(chǎn)生20px的距離,解決方案是在float的標(biāo)簽樣式控制中加入 ——_display:inline;將其轉(zhuǎn)化為行內(nèi)屬性。(_這個符號只有ie6會識別)
漸進(jìn)識別的方式,從總體中逐漸排除局部。
首先,巧妙的使用“\9”這一標(biāo)記,將IE游覽器從所有情況中分離出來。
接著,再次使用“+”將IE8和IE7、IE6分離開來,這樣IE8已經(jīng)獨(dú)立識別。
css
.bb{
background-color:#f1ee18;/*所有識別*/
.background-color:#00deff\9; /*IE6、7、8識別*/
+background-color:#a200ff;/*IE6、7識別*/
_background-color:#1e0bd1;/*IE6識別*/
}
* IE下,可以使用獲取常規(guī)屬性的方法來獲取自定義屬性,
也可以使用getAttribute()獲取自定義屬性;
Firefox下,只能使用getAttribute()獲取自定義屬性.
解決方法:統(tǒng)一通過getAttribute()獲取自定義屬性.
* IE下,even對象有x,y屬性,但是沒有pageX,pageY屬性;
Firefox下,event對象有pageX,pageY屬性,但是沒有x,y屬性.
* (條件注釋)缺點(diǎn)是在IE瀏覽器下可能會增加額外的HTTP請求數(shù)。
* Chrome 中文界面下默認(rèn)會將小于 12px 的文本強(qiáng)制按照 12px 顯示, 可通過加入 CSS 屬性 -webkit-text-size-adjust: none; 解決.
超鏈接訪問過后hover樣式就不出現(xiàn)了 被點(diǎn)擊訪問過的超鏈接樣式不在具有hover和active了解決方法是改變CSS屬性的排列順序:
L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}
!important > id > class > 標(biāo)簽
!important 比 內(nèi)聯(lián)優(yōu)先級高
可繼承: font-size font-family color, ul li dl dd dt;
不可繼承 :border padding margin width height ;
講 DOM 先從 HTML 講起,講 HTML 先從 XML 講起。XML 是一種可擴(kuò)展的標(biāo)記語言,所謂可擴(kuò)展就是它可以描述任何結(jié)構(gòu)化的數(shù)據(jù),它是一棵樹!
document.write只能重繪整個頁面
innerHTML可以重繪頁面的一部分
createDocumentFragment() //創(chuàng)建一個DOM片段
createElement() //創(chuàng)建一個具體的元素
createTextNode() //創(chuàng)建一個文本節(jié)點(diǎn)
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子節(jié)點(diǎn)前插入一個新的子節(jié)點(diǎn)
getElementsByTagName() //通過標(biāo)簽名稱
getElementsByName() //通過元素的Name屬性的值(IE容錯能力較強(qiáng),會得到一個數(shù)組,其中包括id等于name值的)
getElementById() //通過元素Id,唯一性
attribute是dom元素在文檔中作為html標(biāo)簽擁有的屬性;
property就是dom元素在js中作為對象擁有的屬性。
所以:
對于html的標(biāo)準(zhǔn)屬性來說,attribute和property是同步的,是會自動更新的,
但是對于自定義的屬性來說,他們是不同步的,
src用于替換當(dāng)前元素,href用于在當(dāng)前文檔和引用資源之間確立聯(lián)系。
src是source的縮寫,指向外部資源的位置,指向的內(nèi)容將會嵌入到文檔中當(dāng)前標(biāo)簽所在位置;在請求src資源時會將其指向的資源下載并應(yīng)用到文檔內(nèi),當(dāng)瀏覽器解析到該元素時,會暫停其他資源的下載和處理,直到將該資源加載、編譯、執(zhí)行完畢,圖片和框架等元素也如此,類似于將所指向資源嵌入當(dāng)前標(biāo)簽內(nèi)。這也是為什么將js腳本放在底部而不是頭部。
Src source,指向外部資源的位置,如果我們添加<script src ="js.js"></script>瀏覽器會暫停其他資源的下載和處理,直到該資源加載,編譯,執(zhí)行完畢(圖片和框架也是如此),這也就是為什么js腳本要放在底部。
src用于替換當(dāng)前元素,href用于在當(dāng)前文檔和引入資源之間建立聯(lián)系。
cookie 本身不是用來做服務(wù)器端存儲的(計算機(jī)領(lǐng)域有很多這種“狗拿耗子”的例子,例如 CSS 中的 float),它是設(shè)計用來在服務(wù)器和客戶端進(jìn)行信息傳遞的,因此我們的每個 HTTP 請求都帶著 cookie。但是 cookie 也具備瀏覽器端存儲的能力(例如記住用戶名和密碼),因此就被開發(fā)者用上了。
使用起來也非常簡單,document.cookie = ....即可。
但是 cookie 有它致命的缺點(diǎn):
存儲量太小,只有 4KB
所有 HTTP 請求都帶著,會影響獲取資源的效率
API 簡單,需要封裝才能用
后來,HTML5 標(biāo)準(zhǔn)就帶來了sessionStorage和localStorage,先拿localStorage來說,它是專門為了瀏覽器端緩存而設(shè)計的。
存儲量增大到 5MB
不會帶到 HTTP 請求中
API 適用于數(shù)據(jù)存儲 localStorage.setItem(key, value) localStorage.getItem(key)
sessionStorage的區(qū)別就在于它是根據(jù) session 過去時間而實現(xiàn),而localStorage會永久有效,應(yīng)用場景不同。例如,一些需要及時失效的重要信息放在sessionStorage中,一些不重要但是不經(jīng)常設(shè)置的信息,放在localStorage中。
標(biāo)簽閉合、標(biāo)簽小寫、不亂嵌套、提高搜索機(jī)器人搜索幾率、使用外 鏈css和js腳本、結(jié)構(gòu)行為表現(xiàn)的分離、文件下載與頁面速度更快、內(nèi)容能被更多的用戶所訪問、內(nèi)容能被更廣泛的設(shè)備所訪問、更少的代碼和組件,容易維 護(hù)、改版方便,不需要變動頁面內(nèi)容、提供打印版本而不需要復(fù)制內(nèi)容、提高網(wǎng)站易用性;
管它們的 DRAM 內(nèi)目標(biāo)行刷新 (TRR,Target Row Refresh) 緩解,一些最新的 DDR4 模塊仍然容易受到多行 Rowhammer 位翻轉(zhuǎn)的影響。 雖然這些位翻轉(zhuǎn)可以從本機(jī)代碼中利用,但在瀏覽器中從 JavaScript 觸發(fā)它們面臨三個重大挑戰(zhàn)。鑒于 JavaScript 中缺少緩存刷新指令,現(xiàn)有的基于驅(qū)逐(eviction-based)的 Rowhammer 攻擊對于較舊的單行(single-sided)或雙行(double-sided)變體來說已經(jīng)很慢,因此并不總是有效。 使用多行Rowhammer,發(fā)起有效攻擊更具挑戰(zhàn)性,因為它需要從 CPU 緩存中驅(qū)逐許多不同的攻擊者地址,最有效的多行(n-side)需要大量物理連續(xù)的內(nèi)存區(qū)域,這在 JavaScript 中是不可用的。
本文克服了這些挑戰(zhàn),構(gòu)建了SMASH(Synchronized MAny-Sided Hammering),這是一種在現(xiàn)代 DDR4 系統(tǒng)上從 JavaScript 成功觸發(fā) Rowhammer 位翻轉(zhuǎn)的技術(shù)。 為了發(fā)起有效的攻擊,SMASH 利用緩存替換策略的高級知識為基于驅(qū)逐的多行Rowhammer 生成最佳訪問模式。 為了取消對大型物理連續(xù)內(nèi)存區(qū)域的要求,SMASH 將n行 Rowhammer 分解為多個雙行對,使用切片著色來識別它們。 最后,為了繞過 DRAM TRR 緩解措施,SMASH 仔細(xì)安排緩存命中和未命中,以成功觸發(fā)同步的多行 Rowhammer 位翻轉(zhuǎn)。 本研究展示了具有端到端 JavaScript 漏洞的 SMASH,該漏洞平均可以在 15 分鐘內(nèi)完全破壞 Firefox 瀏覽器。
在本文中展示了在現(xiàn)實假設(shè)下,確實可以直接從 JavaScript 繞過 TRR,從而允許攻擊者利用瀏覽器中重新出現(xiàn)的 Rowhammer 漏洞。此外,分析揭示了實際規(guī)避 TRR 的新要求。例如,TRRespass所示快速連續(xù)激活多行可能并不總是足以產(chǎn)生位翻轉(zhuǎn)。 DRAM 訪問的調(diào)度也起著重要作用。
目標(biāo)行刷新:2014 年 Rowhammer 漏洞的發(fā)現(xiàn) 導(dǎo)致了一種全新的攻擊類別,這些攻擊都利用了該漏洞:跨越安全邊界的位翻轉(zhuǎn)。特別是研究人員已經(jīng)證明了對瀏覽器、虛擬機(jī)、服務(wù)器和移動系統(tǒng)的實際攻擊,這些攻擊從本機(jī)代碼、JavaScript 甚至網(wǎng)絡(luò)發(fā)起 。除了這些內(nèi)存損壞攻擊之外,Rowhammer 還可以作為泄漏信息的側(cè)信道。
為應(yīng)對錘擊,制造商使用 in-DRAM TRR 增強(qiáng)了 DDR4 芯片,這是一種 Rowhammer “修復(fù)”,可監(jiān)控 DRAM 訪問以減輕類似 Rowhammer 的活動。 TRR 由兩部分組成:sampler和inhibitor。sampler負(fù)責(zé)對內(nèi)存請求進(jìn)行采樣,以在它們造成危害之前檢測潛在的 Rowhammer 誘導(dǎo)序列。inhibitor試圖通過主動刷新受害者行來避免攻擊。不幸的是,最近TRRespass表明緩解是不夠的,可以通過從雙行移動到多行 Rowhammer 來繞過,即根據(jù)特定的 TRR 實現(xiàn),不僅激活兩行,而且最多激活 19 行。
問題的癥結(jié)在于內(nèi)存芯片的sampler。一個可靠的sampler會采集足夠的樣本來為inhibitor提供足夠準(zhǔn)確的信息,以便在 Rowhammer 攻擊的情況下刷新所有必要的受害者行。不幸的是,常見的sampler實現(xiàn)監(jiān)視有限數(shù)量的攻擊者,并且總是在同一時間 ,隱含地依賴于內(nèi)存請求將以不協(xié)調(diào)、混亂的方式到達(dá)的假設(shè)。然而,如果通過大的物理連續(xù)內(nèi)存區(qū)域精確控制要錘擊的行,并通過顯式緩存刷新(使用 CLFLUSH 指令)積極錘擊多行,多行 Rowhammer 可以壓倒sampler并觸發(fā)位翻轉(zhuǎn),即使在啟用 TRR 的 DRAM。
從 JavaScript 繞過 TRR:雖然本機(jī)代碼 Rowhammer 在現(xiàn)代 DDR4 系統(tǒng)上的復(fù)活確實很嚴(yán)重,尤其是在云和類似環(huán)境中,但它不會立即影響暴露于 JavaScript 攻擊的 Web 用戶。在沒有 CLFLUSH 和對物理連續(xù)內(nèi)存的控制的情況下,如果沒有新的發(fā)現(xiàn),就不可能通過緩存逐出以足夠高的速度誘導(dǎo)位翻轉(zhuǎn)同時繞過 DRAM TRR 來控制大量行.請注意,與雙行 Rowhammer 相比,多行 Rowhammer 模式加劇了這些挑戰(zhàn),因為它們需要更多的物理連續(xù)內(nèi)存和更多的驅(qū)逐。
假設(shè)攻擊者控制了受害者訪問的惡意網(wǎng)站(或良性網(wǎng)站上的惡意廣告)。 攻擊者不依賴任何軟件漏洞,而僅利用 JavaScript 沙箱內(nèi)觸發(fā)的 Rowhammer 位翻轉(zhuǎn)來控制受害者的瀏覽器。 假設(shè)受害者的系統(tǒng)部署了針對 Rowhammer 和側(cè)信道攻擊的所有最先進(jìn)的緩解措施,即現(xiàn)代 DRAM 內(nèi) Rowhammer 緩解措施和針對微架構(gòu)攻擊的瀏覽器緩解措施,包括low-resolution、jittery timers 和針對推測執(zhí)行攻擊的緩解措施。SMASH 依賴透明大頁內(nèi)存(THP,transparent huge page) 來制定其訪問模式。 有關(guān)Linux 發(fā)行版上默認(rèn) THP 設(shè)置的概述,見下表。
從 JavaScript 內(nèi)部執(zhí)行 Rowhammer 攻擊從來都不是一件小事。 攻擊者需要找到一種方法來從緩存中刷新攻擊者,而不依賴于緩存刷新指令。 JavaScript 中缺乏內(nèi)存尋址信息使此類攻擊進(jìn)一步復(fù)雜化。 DRAM 內(nèi) TRR 緩解的競爭對手只會加劇此類挑戰(zhàn)。 由于緩解,普通的雙行 Rowhammer 將不再足夠。 要攻擊啟用 TRR 的 DDR4,攻擊者需要多方面的訪問模式。
挑戰(zhàn)1:要構(gòu)建多行訪問模式,攻擊者需要大量的物理內(nèi)存,這在JavaScript中很難獲得。
多行模式由許多相鄰的行組成。由于DRAM行地址是由高物理地址位決定的,收集相鄰行需要相對大量的物理內(nèi)存。如后所示,SMASH 通過應(yīng)用有關(guān)多行 Rowhammer 的新見解來應(yīng)對這一挑戰(zhàn),這允許它收集所需的攻擊者或地址,而無需大量連續(xù)的物理內(nèi)存塊。
攻擊者面臨的下一個障礙是:如何確保每個內(nèi)存訪問都進(jìn)入 DRAM(而不是其中一個緩存)?攻擊者可以嘗試采用已知的解決方案,例如 Rowhammer.js提出的技術(shù)。這些方法使用驅(qū)逐集來創(chuàng)建 CLFLUSH 自由訪問模式。
挑戰(zhàn)2:攻擊者需要找到一種策略,生成能夠有效地執(zhí)行多行漫游器的模式,而不會引入太多額外的緩存命中。
如下所示,SMASH 通過設(shè)計最佳訪問模式來解決這一挑戰(zhàn),以確保所有緩存未命中都落在攻擊者行上并有助于錘擊。
所做的下一個重要觀察是關(guān)于緩存命中和緩存未命中的順序。普遍的看法是,只要在給定的時間內(nèi)向內(nèi)存發(fā)送了足夠多的請求,就有可能觸發(fā) Rowhammer 位翻轉(zhuǎn)。上圖中總結(jié)的另一個實驗表明,這不適用于具有 in-DRAM TRR 的 DDR4 設(shè)備。在一種情況下,為 18行模式批量發(fā)送 18 個內(nèi)存請求,然后是從緩存中刷新攻擊者的 CLFLUSH 指令。確認(rèn)此模式會觸發(fā)位翻轉(zhuǎn),但是如果將 CLFLUSH 指令與對攻擊者行的內(nèi)存請求交錯,盡管在給定時間段內(nèi)發(fā)送了相同數(shù)量的請求,也無法再觸發(fā)位翻轉(zhuǎn)。正如稍后展示的,這是由于 TRR 緩解的特性。
挑戰(zhàn)3:攻擊者必須仔細(xì)安排緩存命中順序,才能成功繞過DRAMTRR緩解。
如下所示,SMASH 通過將 DRAM 訪問與 TRR 緩解同步來解決這一挑戰(zhàn)。
TRRespass 需要比現(xiàn)代操作系統(tǒng)提供的更大的連續(xù)內(nèi)存分配,以控制每個攻擊者的位置。這是物理內(nèi)存和 DRAM 地址之間映射的結(jié)果——以及操作系統(tǒng)向用戶空間應(yīng)用程序提供物理內(nèi)存范圍的方式(參見下圖)。例如,為了構(gòu)建一個 19 行的模式,TRRespass 發(fā)現(xiàn)該模式對本文的一個測試有效,攻擊者需要 2^(17+log2^37) = 4.63MB 的連續(xù)物理因為 DRAM 行地址從高階物理地址位 17 開始,總共需要 2 · 19-1 = 37 行,包括受害者行,以形成 19行模式。從 JavaScript 沙箱的受限環(huán)境中獲取此類分配并非易事。
JavaScript 中的連續(xù)內(nèi)存:為了從 JavaScript 中獲得對 DRAM 行地址的控制,先前的工作依賴于兩種技術(shù)來獲得連續(xù)分配:(i) 2 MB 透明大頁 (THP) 或 (ii) massaging buddy allocator以獲得高階分配(最大 4 MB)。這兩種技術(shù)都不允許獲得執(zhí)行 19行Rowhammer 所需的 4.63 MB 連續(xù)物理內(nèi)存。
放寬限制:在最初的一項實驗中,試圖了解在嘗試?yán)@過 DRAM TRR 時行位置的影響。從輔助雙行模式開(即由任意行“護(hù)送”的雙行對)。本研究實現(xiàn)了它的概括:N-輔助雙行。即,單個雙行對伴隨著 N 個虛擬行的模式。這意味著 19行模式變?yōu)殡p行模式,N = 19-2 = 17 個傀儡。在特定的 DIMM 上,這些傀儡的位置很重要,在測實驗中,沒有觀察到同一組內(nèi)任意位置傀儡行的翻轉(zhuǎn)次數(shù)有任何明顯差異。這意味著攻擊者只需要形成一個雙行對和 N 個虛擬行映射到同一個存儲體——將展示一個更容易滿足的要求。
最小可行分配:DRAM 行地址由應(yīng)用于物理地址的線性函數(shù)的結(jié)果決定。這些函數(shù)只是將高位物理地址位映射到行地址(見上圖)。由于 N 輔助雙行的發(fā)現(xiàn),現(xiàn)在只需要控制三個相鄰的 DRAM 行:兩個侵略者行和中間的受害者行。換句話說,只需要控制 DRAM 行地址的兩個 LSB。
為了找出需要多少連續(xù)物理內(nèi)存(或這兩個 LSB 在物理地址中的位置),對大多數(shù)現(xiàn)代英特爾 CPU 的 DRAM 尋址函數(shù)進(jìn)行了逆向工程。 它們可以在上表中找到。
鑒于這些特定函數(shù),上表顯示了控制一對雙行需要多少連續(xù)物理內(nèi)存。如前所述,大頁面提供了 2 MB 的連續(xù)物理內(nèi)存,通過massaging伙伴系統(tǒng)內(nèi)存分配器,可以獲得 4 MB。因此得出結(jié)論,在大多數(shù)情況下,大頁面就足夠了。它們僅適用于大型配置,例如使用兩個以上 DRAM 通道的系統(tǒng)。
Rowhammer 的有效性在很大程度上取決于攻擊者激活率的最優(yōu)性(即,固定時間間隔內(nèi)的激活次數(shù))。正如前文中所解釋的,先前工作中描述的基于驅(qū)逐的 Rowhammer 技術(shù)雖然在 DDR3 系統(tǒng)上有效,但不會產(chǎn)生足夠的內(nèi)存訪問來觸發(fā) DDR4 系統(tǒng)上的位翻轉(zhuǎn)需要 Rowhammer 模式。這需要更新的驅(qū)逐策略來最大化錘擊吞吐量。
例如一種基于驅(qū)逐的 Rowhammer 的方法通過利用 LLC的類似 LRU 的替換策略,為每個攻擊者引入了一個緩存未命中。在雙行 Rowhammer 的情況下,這轉(zhuǎn)化為對 DRAM 的兩次額外訪問。然而,每個額外的攻擊者都會引入另一個額外的訪問,因此該方法不能擴(kuò)展到多方面的模式。
前文中解釋了虛擬行(即用于分散 TRR 緩解的行)的位置無關(guān)緊要。在本節(jié)中,將展示也可以通過使用虛擬行進(jìn)行逐出來消除所有額外的 DRAM 訪問。
本文的自驅(qū)逐 Rowhammer 模式的目標(biāo)是使用傀儡繞過 in-DRAM TRR sampler,同時驅(qū)逐緩存。為了便于討論,首先定義將在本文其余部分使用的術(shù)語。
術(shù)語:如前所述,雙行對是映射到同一銀行中第三行(即受害者)周圍的兩行(即攻擊者)的一對地址。讓 (a,b) 表示具有虛擬地址 a 和 b 的雙行對。如果虛擬地址 d 與 a 位于同一組中,則虛擬地址 d 是 (a,b) 的虛擬地址,因此也與 b 位于同一組中,并且不等于任何一個。建立這些定義后,按訪問順序排列的 N 輔助雙行模式如下所示:
其中 di 表示 (a,b) 的第 (i + 1) 個傀儡。在 dN-1 之后,再次訪問 a。將使用術(shù)語 aggressor 來指代 a、b 或一個虛擬地址。此外,使用 A 和 B 分別指代 a 和 b 的緩存集。
現(xiàn)在能夠更準(zhǔn)確地說明本研究意圖,使用虛擬對象 di 來從 CPU 緩存中逐出 a 和 b。為此,將它們分成大小相等的兩組,如下所示:d2k虛擬映射到 A,d2k+1 虛擬映射到 B,k 是從 0 到 N/2 的整數(shù)。基本上是在創(chuàng)建一個類似zebra的模式,其中每個其他地址都映射到同一組。
構(gòu)建驅(qū)逐集:為了實現(xiàn)自我驅(qū)逐的目標(biāo),需要確保虛擬地址不僅與 (a,b) 位于同一存儲體,而且還與 a 或 b 一致,即它們映射到相同的緩存集。不幸的是,能夠分配 2 MB 連續(xù)物理內(nèi)存的攻擊者無法控制用于索引 CPU 緩存切片的高階物理地址位(即位 20 以上的位)。在頁面著色算法的幫助下解決了這個問題,該算法允許發(fā)現(xiàn)看似無法訪問的高階切片位。
大頁面著色:考慮一個攻擊者可以使用一組 2 MB 大頁面。然后,大頁面的顏色由僅應(yīng)用于大頁面偏移量上方的切片位的切片散列函數(shù)的結(jié)果給出。由于攻擊者已經(jīng)控制了頁面偏移內(nèi)的切片位,使用已知的頁面顏色,攻擊者可以完全控制切片索引。
為了揭示大頁面的顏色,攻擊者利用基于緩存驅(qū)逐的側(cè)信道。舉例來說,假設(shè) LLC 的結(jié)合性是 W = 1。有兩個大頁面 P 和 Q,想知道它們的顏色是相同還是不同。為了找出答案,選擇一個任意的頁面偏移 f 并創(chuàng)建兩個地址 p 和 q,每個頁面一個,但都在頁面偏移 f 處,以確保它們在頁面內(nèi)的設(shè)置索引和切片位相等。然后訪問 p,然后是 q,再次是 p。如果對 p 的第二次訪問導(dǎo)致(慢速)緩存未命中,則高位切片位的散列或 P 和 Q 的等效頁面顏色相等,否則它們不同。
首先選擇雙行對(a,b)。為了找到一個,攻擊者在已知的彩色大頁面之一中選擇任意偏移量。然后,為了找到 b,將 a 的行地址加二(或減二)。還更改了 b 中的一些附加位,以確保添加后 a 和 b 仍映射到同一組。 接下來選擇虛擬地址在與 (a,b) 相同的頁面偏移量處,但來自相同顏色的不同大頁面。在相同顏色的頁面上使用相同的偏移量,確保與 a 映射到 A 的偏移量相同的傀儡,以及 b 偏移量處的傀儡映射到 B。此外,傀儡將自動位于同一位置與 (a,b) 相同的存儲體。
現(xiàn)在有了雙行對 (a,b) 和傀儡。原則上,假設(shè)傀儡映射到 A 或 B,N 輔助雙行模式是自驅(qū)逐的。然而在實踐中,如果虛擬對象不都適合它們的緩存集,它們只會相互驅(qū)逐或驅(qū)逐雙行對。特別是,長度 L = N +2 的 N 輔助雙行模式僅在 L/2 > W 時才會自驅(qū)逐,其中 W 是 LLC 的關(guān)聯(lián)性。這將嚴(yán)重限制 SMASH 只能使用非常多的 N。
命中:必須引入另一種地址,將其稱為命中(如緩存命中)。命中是永遠(yuǎn)不應(yīng)該離開 LLC 的地址,并且像傀儡一樣,它們要么映射到 A 要么映射到 B。也就是說,h2k 與 a 和 d2k 是一致的,而 h2k+1 與 b 和 d2k+1 一致對于某些整數(shù)k。命中用于有效地將 LLC 的感知關(guān)聯(lián)性降低到 W’ < W。例如,使用命中,即使 LLC 的關(guān)聯(lián)性更大,輔助雙行模式(每組有四個攻擊者)也可以自驅(qū)逐比四個,實際情況就是這樣。對于命中,這種 6 輔助雙行模式可能如下所示:
每行正好包含填滿 A 和 B 的 2W 次訪問。每行上的前四次訪問進(jìn)入 DRAM,并逐出另一行上的前四次。例如,在等式 2 中,d2 驅(qū)逐 A 中的 a,d3 驅(qū)逐 B 中的 b,d4 再次驅(qū)逐 A 中的 d0,等等。下圖顯示了另一個示例,W’ = 3 的 16 輔助雙行模式。
隨著命中的引入,還引入了一個新參數(shù),即在模式中引入了多少。至少需要確保模式不適合 A 和 B(否則將不會有驅(qū)逐),因此必須至少將 W-L/2 添加到長度為 L 的模式中。 其次,它不會使引入超過 2(W-1) 的意義,因為 A 和 B 中沒有空間留給攻擊者。第三,請注意,如果 W’ 不劃分 L/2(它在等式 2 中進(jìn)行,其中 W’ = 2 和 L/2 = 4),訪問順序變得有點(diǎn)復(fù)雜,例如如果 W’ = 3 得到:
處理 QLRU:到目前為止,已經(jīng)隱含地假設(shè)了一個類似 LRU 的替換策略。現(xiàn)在演示如何放寬這一假設(shè)以創(chuàng)建使用 Quad-age LRU (QLRU) 自我驅(qū)逐的模式,這是現(xiàn)代英特爾 CPU 的 LLC 使用的實際替換策略。下圖顯示了自驅(qū)逐下緩存集 A 的演變,說明了降低關(guān)聯(lián)性 W’ = 1 下的 QLRU 行為3,這意味著在每個集訪問一個攻擊者后,立即轉(zhuǎn)向命中。將從 1 開始,在 5 結(jié)束,6 表示下一輪的開始。
首先1訪問 a,它被帶入集合 A 并替換最舊和最左邊的緩存行。 2 由于此時所有行的時間都為 3(可能是最舊),因此 a 會在最左邊的位置結(jié)束。因為 a 是新的,所以它的時間變成1。 3繼續(xù)造成五個緩存命中,訪問當(dāng)前在緩存中但時間為 3 的每個其他緩存行。 4 訪問它們會使他們的時間回到原來的水平。 5 最后,因為現(xiàn)在所有時間都是一,所以替換策略說他們都應(yīng)該變成三個,這是通過時間更新來完成的。 6 現(xiàn)在回到開頭,a 位于 LRU 位置,準(zhǔn)備在攻擊者訪問到 A 的第一個虛擬映射即 d0 時被驅(qū)逐。
最后為了使模式更快,使用雙指針雕鏤(Pointer chase)來執(zhí)行訪問,而不是更常見的單指針雕鏤。 在單個(寄存器)指針雕鏤中,攻擊者指向的內(nèi)存位置提供下一個攻擊者的地址(或者有時是命中,就像例子中一樣)。 然而,這種方法并沒有最大限度地提高內(nèi)存吞吐量,因為每第二次內(nèi)存訪問都需要等到第一次訪問完成,從而降低了內(nèi)存控制器級別的并行度。
為此沒有使用一個寄存器,而是使用了兩個。 自然地將模式分成兩半,每一半中的地址映射到 A 或 B。然后將兩半鏈接到相互關(guān)聯(lián)的兩個單指針雕鏤中。 結(jié)果是這樣的
每條指令從內(nèi)存加載,而不是存儲。 實驗表明與使用單指針追逐相比,雙指針追逐提高了 80% 的內(nèi)存吞吐量。
本節(jié)中介紹的自驅(qū)逐模式不能直接觸發(fā)位翻轉(zhuǎn),即使雙行對包含已知易受攻擊的行也不能。這意味著單靠多行 Rowhammer 并不總是足以繞過 TRR。為了對此進(jìn)行研究,必須了解可以觸發(fā)位翻轉(zhuǎn)中基于“收集”CLFLUSH 的模式(即基準(zhǔn)模式)與不能觸發(fā)位翻轉(zhuǎn)的自驅(qū)逐模式之間的區(qū)別。
在本節(jié)中,將闡明攻擊者如何以 S0 為案例研究來制作 Rowhammer 誘導(dǎo)的同步自驅(qū)逐模式。一種系統(tǒng)配置通常容易受到多種多行模式的影響。這一事實簡化了最終實現(xiàn),因為攻擊者可以選擇具有最佳攻擊者行數(shù)的模式,以改進(jìn)驅(qū)逐過程。因此,選擇使用 18 行(或者更確切地說,16 行輔助雙行) 。如上圖-a 所示,基準(zhǔn)模式遍歷攻擊者,連續(xù)發(fā)出內(nèi)存請求,然后使用 x86 64 CLFLUSH 指令刷新這些地址。測試機(jī)配備了 Intel i7-7700K CPU,具有 16 路組關(guān)聯(lián) LLC(即 W = 16)。選擇設(shè)置約化關(guān)聯(lián)性 W’ = 3。作為示例,自驅(qū)逐模式如下所示(雙行對、八對傀儡和 26 次命中,見上圖-b):
鑒于此模式比基準(zhǔn)模式快約 30%,令人驚訝的是它不會產(chǎn)生位翻轉(zhuǎn)。因此嘗試減慢此模式以使其以與基準(zhǔn)模式相同的速度執(zhí)行。
為了研究這種現(xiàn)象,通過在 (a,b) 前面添加額外的 NOP 來減緩模式。這樣,激活間隔增加。結(jié)果如下圖所示:
1.首先,能夠?qū)?nèi)存請求與發(fā)送到 DRAM 的刷新命令同步。確切地說,當(dāng) t(即迭代公式 4 的模式一次的時間)或 2t 除以 tREFI 時,盡管 NOP 數(shù)量增加,但兩種模式都停止減速并且曲線變平。
2.其次,如果模式太快,即tREFI/t > 5,則不會觸發(fā)位翻轉(zhuǎn)。
in-DRAM TRR對每個刷新命令起作用,并且sampler的每個刷新間隔可以采樣多個攻擊者。在所有實驗中,只在與第一個 nnS 攻擊者相鄰的受害者行中發(fā)現(xiàn)位翻轉(zhuǎn),其中 n 始終是攻擊者的總數(shù),S 是sampler的可疑容量,就其跟蹤的攻擊者數(shù)量而言。只是通過減少攻擊者的數(shù)量來學(xué)習(xí) S,直到不再能夠重現(xiàn)特定的位翻轉(zhuǎn)。
存儲器控制器需要平均每 tREFI = 7.8 μs 調(diào)度一次刷新命令。現(xiàn)代內(nèi)存控制器試圖通過在沒有 DRAM 活動時機(jī)會性地發(fā)送刷新命令來提高性能。為了成功觸發(fā) Rowhammer 位翻轉(zhuǎn),模式需要重復(fù)數(shù)萬次,在此期間內(nèi)存控制器必須發(fā)出許多刷新命令。當(dāng)沒有 NOP 時,內(nèi)存控制器將嘗試在具有許多緩存命中的區(qū)域之一期間安排刷新命令。這意味著,當(dāng)刷新命令到達(dá)緩存命中的三個不同區(qū)域時,TRR 機(jī)制將能夠成功地采樣和刷新公式 4 模式中的 18 個攻擊者行中的每一個。
當(dāng)在模式前面插入 NOP 時,可能會發(fā)生三種不同的情況,如前圖所示。 在第一個場景中,在 NOP 數(shù)量較少的情況下,內(nèi)存控制器可能仍會選擇發(fā)送在具有緩存命中的區(qū)域中刷新命令,導(dǎo)致沒有位翻轉(zhuǎn)。在第二種情況下,每個模式前面的大量翻轉(zhuǎn)會使模式太慢而無法觸發(fā)位翻轉(zhuǎn)。在第三種情況下,使用正確數(shù)量的 NOP,模式與內(nèi)存控制器打算發(fā)送刷新命令的時間同步。這導(dǎo)致第一個攻擊者 (a,b) 逃脫 TRR 機(jī)制以成功錘擊內(nèi)存并觸發(fā)位翻轉(zhuǎn)。
雖然在自驅(qū)逐模式的開頭添加 NOP 的策略在觸發(fā)位翻轉(zhuǎn)方面是有效的,但它需要攻擊者非常精確地與刷新命令同步,并找出成功攻擊的正確 NOP 數(shù)量。雖然這是一個合理的策略,正如將在評估中展示的那樣,但在 JavaScript 中與刷新間隔精確同步并不總是微不足道的。相反,將描述另一種創(chuàng)建模式的策略,該模式僅與內(nèi)存控制器的刷新命令進(jìn)行軟同步,并取消找到有效錘擊的確切 NOP 數(shù)量的要求。
為了確保內(nèi)存控制器不會在不需要的時刻進(jìn)行刷新,必須確保具有緩存命中的區(qū)域足夠小。為此,稍微修改了自驅(qū)逐訪問模式,以在緩存未命中之間更均勻地分配緩存命中,從而創(chuàng)建以下自驅(qū)逐模式:
上圖顯示了在前面使用可變數(shù)量的 NOP 執(zhí)行此模式的結(jié)果。鑒于少量緩存命中并沒有為內(nèi)存控制器提供足夠大的窗口來調(diào)度刷新,它會機(jī)會性地使用單個可用的 NOP 間隙來代替調(diào)度刷新命令。因此,公式 5 的模式可以更柔和地與刷新命令同步,而無需精確數(shù)量的 NOP。這使得從 JavaScript 搜索位翻轉(zhuǎn)更加方便,如下一節(jié)所示。
調(diào)整緩存切片:在這些實驗中發(fā)現(xiàn)訪問不同切片可能需要可變的時間。這使得生成同步模式變得更加困難,其中地址映射到的兩個集合 A 和 B 駐留在不同的切片中。因此,通過調(diào)整每個地址的列位,確保 A 和 B 映射到同一個切片。
上一節(jié)表明,可以成功生成自驅(qū)逐錘擊模式,這些模式能夠使用軟同步技術(shù)和重新操作來繞過 TRR 機(jī)制。還展示了正確選擇攻擊者地址的能力取決于虛擬到 DRAM 尋址功能以及如何選擇映射到給定緩存集和切片的地址。
在本節(jié)中,評估攻擊者可以成功創(chuàng)建有效的自驅(qū)逐模式的約束條件。本文評估了在來自兩個主要內(nèi)存供應(yīng)商的具有不同內(nèi)存配置和內(nèi)存模塊的三種設(shè)置上構(gòu)建自驅(qū)逐模式的可行性(見上表)。所有系統(tǒng)均采用采用 Kaby Lake 微架構(gòu)的 Intel Core i7-7700K CPU。由于 Skylake、Kaby Lake、Coffee Lake (R) 微架構(gòu)都對給定的內(nèi)存配置使用相同的 DRAM 尋址函數(shù),正如前文中發(fā)現(xiàn)的那樣,關(guān)注在不同內(nèi)存配置上構(gòu)建自驅(qū)逐同步模式的可行性在 CPU 的微體系結(jié)構(gòu)方面不乏通用性。
是否可以僅從大頁面中提取自驅(qū)逐模式,取決于內(nèi)存控制器采用的 DRAM 尋址功能。在較小程度上,它還取決于用于切片尋址的復(fù)雜尋址方案,自 Sandy Bridge 以來,這種方案沒有改變,除了從 Skylake 開始,切片的數(shù)量等于超線程的數(shù)量而不是內(nèi)核的數(shù)量。
使用基于軟件的 DRAMA 方法對幾種內(nèi)存配置的物理到 DRAM 尋址功能進(jìn)行了逆向工程。上表顯示了為獲得 (a,b) 形式的雙行對而需要更改的位。假設(shè)啟用了 THP,在七種可能配置中的六種中,可以成功地在大頁面內(nèi)找到雙行對。在其余情況下,行位在大頁邊界之后開始,因此找不到與 a 相隔兩行的 b。
首先使用開源 TRRespass為的三個測試中的每一個找到最有效的多行訪問模式。然后,根據(jù)前文中描述的策略使每個模式自驅(qū)逐和同步。下表總結(jié)了所得模式的一些不同屬性(例如,降低的關(guān)聯(lián)性 W’)。
下表顯示所有三種自驅(qū)逐模式都能夠使用原生 C 實現(xiàn)觸發(fā)位翻轉(zhuǎn)。同時,觀察到不同系統(tǒng)所需的 NOP 數(shù)量存在明顯差異。特別是,與系統(tǒng) S0 相比,系統(tǒng) S1 和 S2 上的“有效 NOP 范圍”更窄。懷疑這是因為 S1 和 S2 構(gòu)建的自驅(qū)逐模式的相對緩慢(與刷新模式相比)造成的。如上表所示,與 S0 相比,S1 和 S2 的 TRRespass 模式更小(即所需的傀儡更少),這意味著命中的引入將對 (a,b) 的激活之間的時間產(chǎn)生更大的相對影響。因此,使用太多 NOP 會使這些模式太慢而無法觸發(fā)位翻轉(zhuǎn)。
在 JavaScript 中的實現(xiàn)能夠觸發(fā)系統(tǒng) S0 和 S1 上的位翻轉(zhuǎn)。觀察到與 S0 相比,S1 上位翻轉(zhuǎn)的發(fā)生頻率較低。盡管使用原生實現(xiàn)也觀察到了這一點(diǎn),但與 S0 相比,系統(tǒng) S1 和 S2 的更嚴(yán)格的同步要求(即更小的 NOP 范圍)會夸大差異是合理的。由于 NOP 在 JavaScript 中不可用,實現(xiàn)使用 XOR 代替。這兩條指令都很便宜,但 JavaScript 中的 XOR 循環(huán)有更多的開銷,因此引入了更粗粒度的延遲。這使得瞄準(zhǔn)系統(tǒng) S1 和 S2 的最佳位置變得更加困難。
現(xiàn)在評估運(yùn)行在最新版本的 Mozilla 的 JavaScript 運(yùn)行時 SpiderMonkey 上的 JavaScript 實現(xiàn)的性能。特別地,考慮了程序的初始化階段(例如檢測頁面顏色所花費(fèi)的時間)和錘擊階段。
初始化:攻擊者首先運(yùn)行切分著色算法,以揭示支持其 ArrayBuffer 的 500 個大頁面的頁面顏色。接下來,攻擊者使用大頁面的子集(其大小取決于模式的長度)來組裝第一個自驅(qū)逐模式。最后,攻擊者需要注意同步,并通過改變模式前面的 XOR 數(shù)量來做到這一點(diǎn)。
上圖報告了在每個步驟上花費(fèi)的時間:“第一個驅(qū)逐集”和“上色 500 大頁”。一起報告切片著色算法找到五個相同顏色的大頁面并隨后使用它們分別顯示其他 500 個頁面的顏色所需的時間。最后,“軟同步”。報告為軟同步尋找正確數(shù)量的 XOR 所花費(fèi)的時間。每次測量都重復(fù)了 10 次。平均而言,攻擊者需要一分鐘才能完成初始化。請注意,軟同步步驟花費(fèi)的時間最長。在實現(xiàn)中,使用放大的時間測量來估計模式在將其用于錘擊之前適合 7.8 μs 的刷新間隔 tREFI 的次數(shù)。如果模式適合四次,那么它是一個很好的錘擊候選者。
錘擊時間:初始化完成后,攻擊者開始尋找可利用的位翻轉(zhuǎn)。為了錘擊不同的行,攻擊者只需更改用于模式組裝的大頁面子集。上圖顯示了在 S0 和 S1 上的單個 10 小時實驗期間隨時間推移的唯一位翻轉(zhuǎn)的累積數(shù)量。
要成功執(zhí)行 SMASH,攻擊者需要了解受害者的內(nèi)存配置。特別是,如果不知道 DRAM 尋址功能和至少一種繞過 TRR 的 n 行模式,就不可能構(gòu)建自驅(qū)逐模式。雖然指紋可以檢測特定系統(tǒng),但攻擊者也可以嘗試不同的配置,直到成功。
在硬件中緩解 Rowhammer:Rowhammer 是 DRAM 硬件中的一個漏洞,期望它應(yīng)該在硬件中修復(fù)是明智的。不幸的是,更新和更有效的緩解措施需要很多年才能到達(dá)終端用戶。此外,鑒于未來的 DRAM 設(shè)備將采用更小的晶體管,是否有可能為此類設(shè)備構(gòu)建有效的緩解措施還有待觀察。盡管如此,未來 DRAM 設(shè)備的安全性可以從三個方向提高:首先,硬件制造商可以以更高的成本構(gòu)建更精確的sampler,無論是在 DRAM 設(shè)備內(nèi)部還是在內(nèi)存控制器上。其次,可以部署比現(xiàn)有解決方案更積極的糾錯,以降低觸發(fā)位翻轉(zhuǎn)的概率。第三,根據(jù)訪問模式和給定 DRAM 設(shè)備的脆弱性,可以限制潛在激活的數(shù)量。所有三個方向都伴隨著性能或存儲開銷,更不用說額外的功耗了。
在軟件中緩解 Rowhammer:在硬件緩解措施可用的情況下,已經(jīng)有許多建議可以在軟件中緩解 Rowhammer。它們的安全性、兼容性或性能總是存在問題。 CATT建議使用保護(hù)頁來保護(hù)內(nèi)核內(nèi)存免受用戶內(nèi)存的攻擊。不幸的是,內(nèi)核內(nèi)存可能會通過頁面緩存等常見機(jī)制直接暴露給用戶內(nèi)存,從而使系統(tǒng)暴露在外。 ALIS和GuardION試圖保護(hù)系統(tǒng)的其余部分免受可能被攻擊的內(nèi)存區(qū)域,但這些解決方案需要對每個軟件進(jìn)行更改,而且不能保護(hù)系統(tǒng)的其余部分免受攻擊。 ZebRAM嘗試使用奇數(shù)行和偶數(shù)行將 VM 的內(nèi)存劃分為安全和不安全區(qū)域。虛擬機(jī)可以直接訪問安全區(qū),而不安全區(qū)則用作受 ECC 保護(hù)的交換緩存。 ZebRAM 的設(shè)計雖然可以抵御已知攻擊,但在處理內(nèi)存密集型工作負(fù)載時具有非平凡的性能開銷。
減輕 SMASH:現(xiàn)在討論更實用的緩解措施,這些緩解措施在不解決底層Rowhammer漏洞的情況下讓攻擊者更難通過SMASH來利用瀏覽器。當(dāng)前版本的 SMASH 依靠 THP 來構(gòu)建高效的自驅(qū)逐模式。禁用 THP,同時引入一些性能開銷,將停止 SMASH 的當(dāng)前實例。此外,漏洞利用特別依賴于瀏覽器中的破壞指針來破壞 ASLR 并轉(zhuǎn)向偽造對象。保護(hù)軟件或硬件中指針的完整性(例如,使用 PAC)將阻止當(dāng)前的 SMASH 漏洞利用。
本研究展示了互聯(lián)網(wǎng)用戶仍然受到現(xiàn)代 DDR4 設(shè)備中 Rowhammer 漏洞的影響。 這些設(shè)備需要多行 Rowhammer 模式來繞過它們的 TRR 緩解。 在不訪問緩存刷新指令和連續(xù)物理內(nèi)存的情況下,在 JavaScript 中高效執(zhí)行此類模式特別具有挑戰(zhàn)性。 發(fā)現(xiàn)了 TRR 緩解的一個新屬性,結(jié)合精心選擇的錘擊地址,可以在瀏覽器中創(chuàng)建高效的多行Rowhammer 模式。 然而,在 JavaScript 中觸發(fā)位翻轉(zhuǎn)需要更進(jìn)一步,并根據(jù) CPU 內(nèi)存控制器發(fā)出的刷新命令仔細(xì)安排緩存訪問。 端到端漏洞利用稱為 SMASH,可以在平均 15 分鐘內(nèi)啟用所有緩解措施來完全破壞 Firefox 瀏覽器。 最后討論了減輕 Rowhammer 攻擊的未來方向,特別是 SMASH。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。