Rowhammer 漏洞
/ ROW-ham-er /
DRAM 把位元塞得密到難以想像:數十億個微小電容排成緊密的列,每個持有一絲代表 0 或 1 的電荷(見 dram)。Rowhammer 是那令人不安的發現:這些列如今靠得太近,以致對某一列反覆「錘擊」會在電氣上擾動它的鄰居。藉由極快地一遍又一遍讀同一列,攻擊者能從物理上緊鄰它的列洩漏出足夠電荷,翻轉那裡的位元——而那是攻擊者從未獲准寫入的記憶體。這是一種「隔空毀損」,肇因不是邏輯臭蟲,而是把記憶體格塞得太緊的物理。
把機制用淺白的步驟講出來。反覆啟動一條 DRAM 列(打開它來讀)會沿著電線送出電壓擺動,而那些擺動每次都從鄰列流失一點電荷。平常週期性的更新(refresh)會在電荷流失殆盡前把它補回,但若你在兩次更新之間把一條「攻擊者」列啟動上千次,鄰近「受害者」列的洩漏就可能越過門檻,一個儲存的位元自己翻了——1 變 0 或反過來——沒有人寫過它(見 memory-refresh)。可怕的是它的安全後果:位於錯誤位置的一個翻轉位元,可以被轉化成特權提升,例如翻轉分頁表項裡的一個位元,讓某行程獲得對它本不該觸及之記憶體的寫入權(見 page-table-entry 與 memory-protection)。
Rowhammer 被誠實地教成一個單靠軟體權限無法阻止的硬體層級威脅,因為這個攻擊並不違反任何存取規則——攻擊者只讀自己的記憶體,而傷害發生在隔壁的物理裡。它跨越了本領域其餘部分努力執行的那些隔離界線,並已被示範可在瀏覽器內部、以及跨虛擬機之間發動。緩解措施存在但只是局部:偵測並更新被錘擊的列(目標列更新)、能抓到部分翻轉的錯誤更正碼、提高更新頻率——然而研究者不斷找到繞過每一招的辦法。它鮮明地提醒我們:當我們為效能推高密度,物理基底本身就可能成為一個攻擊面。
一個攻擊者行程反覆讀取夾住某條受害者列的兩條 DRAM 列,在兩次更新之間做數十萬次(「雙面錘擊」)。這些電壓活動從受害者列洩漏電荷,直到它的某個位元翻轉。若那個位元恰好住在一個分頁表項裡,這次翻轉就能讓攻擊者行程獲得對它被禁止之記憶體的寫入權——在從未打破任何軟體存取規則的情況下提升特權。
錘擊鄰列翻轉受害者列裡的一個位元;讓這次翻轉落在分頁表項上,就把物理變成了特權提升。
Rowhammer 不違反任何存取規則——攻擊者只讀自己的記憶體,鄰列的位元因物理而翻轉。這就是為什麼純軟體的權限檢查擋不住它,也為什麼緩解措施至今仍只是局部。