問:linux
我剛剛意識到在任何語言裏,當你把密碼保存到一個變量裏,它將以文本的形式存放在內存裏。程序員
我認爲操做系統將發揮做用,禁止進程相互訪問彼此分配的內存。可是我也認爲這多少有些不是靠譜的作法。所以我想知道這是否是真正安全的,是否有更加安全的存儲密碼的方法,來確保外部進程不能訪問它們。算法
我沒有指定操做系統或者語言,由於個人問題是很是廣泛的。這更像是一個計算機常識問題、而不是具體的問題。編程
答:緩存
你點到了一個痛處……安全
從歷史上講,計算機是大型機,容許許多不一樣的用戶在相同的物理機上創建會話和進程。類Unix系統(好比Linux),還有VMS和其相關親戚(和包括全部NT、和此後的2000,XP, Vista, 7, 8…… 的Windows家族,),設計之初是爲了支持大型機模型。這樣,硬件提供權限級別。操做系統最重要的部分是內核,它以最高權限級別運行(是的,我知道對於虛擬化有些微妙),並管理權限級別。應用程序以較低級別運行,內核禁止它讀、寫其餘應用程序的內存。應用程序按頁(page,一般4或8KB)從內核得到RAM。若是一個應用程序試圖訪問另外一個應用程序的頁,內核就會阻止它,而且受到嚴重懲罰(「segmentation fault」, 「general protection fault」)。編程語言
當一個應用程序再也不須要頁(特別是在該應用程序還存在的時候)時,內核會控制該頁,可能會分給另外一個應用程序。現代操做系統在使用這些頁的時候,會「清空」(blank)該頁,這裏的「清空」指「用零填充」,從而阻止數據從一個進程泄露到另外一個進程。注意,Windows 95/98/Millenium沒有清空頁,泄露有時候會出現……可是,這些操做系統是針對單臺機器的單個用戶的。雲計算
固然,有不少繞過內核的方法:應用程序有一些方式來獲取「足夠的權限」(沒有上面權限高的、同種類型權限)。Linux系統有ptrace,內核容許一個進程經過ptrace()讀寫另外一個進程的內存,此時這兩個進程須要運行在同一個用戶ID下,或者運行ptrace()進程的是「root」用戶。類似的功能也存在於Windows。加密
底線是RAM裏的密碼沒有操做系統容許的安全。按照定義,在進程內存裏存儲一些機密數據有個前提,就是你相信操做系統不會把數據給第三方。操做系統是你的朋友,由於若是它是敵人,那麼你就失去了一切。操作系統
有意思的環節到了。既然操做系統負責進程的隔離,仍是有不少人試着找到了穿透防禦的辦法。這裏是他們找到的有趣的辦法……
應用程序看到的「RAM」不是真正須要的「內存」。內核是假象的管理者,分配實際不存在的頁。假象是經過經過磁盤上的專用空間來交換RAM內容,磁盤上的空閒空間是至關大的;這被稱爲虛擬內存。應用程序無需關心,由於內核會根據須要取回這些頁(固然,磁盤比RAM慢不少)。不幸的後果是,一些數據,特別是位於RAM中的數據,使得RAM變成 數據被覆蓋以前的 物理載體。尤爲是當電源被切斷時,它仍然呆在那裏。當壞傢伙搞走這臺機器,隨後就能獲取數據了。或者機器退役後在eBay賣出,系統管理員忘記了完全清除磁盤內容。
Linux提供了一個mlock的系統調用來阻止內核把某些特定的頁發送到swap區。既然鎖住RAM裏的頁可以大大減小其餘進程獲取RAM資源的狀況,那麼你須要一些權限(仍是root)來使用這個功能。
惱人的地方在於,追蹤真正保存在RAM裏的密碼必然是不太容易的。作爲一個程序員,你是經過編程語言提供的抽象方式來訪問RAM的。尤爲是使用垃圾回收的編程語言會明顯地複製RAM裏的對象(由於它對不少GC算法有幫助)。大多數編程語言就是這樣被影響的(像Java, C#/.NET, Javascript, PHP……清單幾乎沒有盡頭)。
hibernation彷佛爲了復仇帶來了一樣的問題。原本,hibernation必須把整個RAM寫回磁盤——包括mlock()涉及的頁,甚至CPU註冊的內容。爲了不hibernation泄露數據,你不得不採起像加密整個磁盤之類的猛烈的措施——這天然意味着只要你喚醒機器,就能夠鍵入解除鎖定的密碼。
大型機模型假定它可以運行一些彼此友好的進程,且保持極好的和平和隔離。現代硬件加重了這一難度。當兩個進程運行在同一個CPU時,它們共享資源,包括緩存內存;內存訪問比緩存以外的任何地方都要快,可是緩存大小十分有限。這催生了一個進程使用來自於另外一個進程的恢復密鑰。使用其餘類緩存的資源變體也有了,好比CPU裏的分支預測(branch prediction)。隨着對高度機密的、集中於密鑰的研究,它可以真正應用於任何數據。
還有種狀況,顯卡可以作直接內存存取(Direct Memory Access,DMA)【注1】。DMA是否不會被濫用去讀寫其餘進程的內存 取決於 文檔不全的硬件、閉源的驅動程序和內核是如何協做確保合適的訪問控制的。我不會爲此賭我一件上次穿過的襯衣的……
結論:是的,當你在RAM存放密碼時,你是相信操做系統會確保機密的。是的,這個任務很艱鉅,甚至在現代系統上是不可能的。若是你的數據高度機密,你就不該該使用大型機模型,也不要容許潛在友好的實體在你的機器上運行代碼。(順便說一句,這意味着託管的虛擬主機和雲計算根本是不安全的。若是你對安全比較在乎,請使用專有硬件。)
注1:DMA:http://zh.wikipedia.org/zh-cn/%E7%9B%B4%E6%8E%A5%E8%A8%98%E6%86%B6%E9%AB%94%E5%AD%98%E5%8F%96