題:
密碼存儲在內存中是否安全?
Antoine Pinsard
2013-01-15 01:30:01 UTC
view on stackexchange narkive permalink

我剛剛意識到,以任何一種語言,當您將密碼保存在變量中時,密碼都會以純文本格式存儲在內存中。

我認為操作系統可以完成其工作,並且禁止進程訪問彼此分配的內存。但是我也認為這是可以繞開的。因此,我想知道它是否真的安全,是否有一種更安全的方法來存儲密碼以確保外部進程無法訪問它們。

我沒有指定操作系統或語言,因為我的問題是很一般。這是一個計算機素養問題,而不是一個特定目的的問題。

這實際上是加密的弱點。任何未加密的值或等待加密的值均以純文本形式存儲在內存中。
您可能會在[此程序員問題](http://programmers.stackexchange.com/questions/181577)中找到一些有用的背景。
我記得Slashdot上有關利用DRAM衰落延遲的取證技術的文章:將RAM芯片從運行中的計算機足夠快地移動到另一台計算機上(該數目完全在人的能力範圍內),您可以輕鬆地丟棄全部內容。
雖然其他答案很好地涵蓋了“安全為...”的細微差別,但如果您擔心的話,您的平台/庫可能具有SecureString或類似的設計,以最大程度地降低風險。一旦您指出使用完畢,這種構造可能會覆蓋其自身的內存,並管理由垃圾回收等引入的自身副本的細微差別。
良好的安全預防措施是盡快覆蓋包含密碼的變量(在C / C ++中比Java更容易),而改用派生密鑰(例如,使用PBKDF2生成)。
@OmarKohl這就是我為腳本所做的。我首先要求密碼解鎖鑰匙圈。然後,我加密發送到遠程計算機的隨機會話密碼。而且,一旦我確定它收到了新密碼,便會覆蓋密鑰環的密碼。如果不能真正解決問題,它將限制實際的永久密碼存儲在內存中的時間。
相關(如Hackernews上的某人所指出的):http://en.wikipedia.org/wiki/TRESOR
HeartBleed不會將部分內存提供給攻擊者嗎?
@jkd是,但是僅來自與易受攻擊的OpenSSL版本鏈接的進程中的內存。不幸的是,這通常包括密碼,但僅適用於該特定過程。
十三 答案:
Thomas Pornin
2013-01-15 03:10:06 UTC
view on stackexchange narkive permalink

您碰到了一個痛處...

從歷史上看,計算機是大型機,許多不同的用戶在其中啟動會話和處理同一台物理機器。構造了類似Unix的系統(例如Linux),還包括VMS及其親戚(該家族包括NT系列的所有Windows,因此包含2000,XP,Vista,7、8 ...),以支持大型機模型。

因此,硬件提供了特權級別。操作系統的核心部分是內核,它以最高特權級別運行(是的,我知道虛擬化方面存在一些細微問題),並且管理特權級別。應用程序以較低級別運行,並且被內核強制阻止讀取或寫入彼此的內存。應用程序從內核通過 pages (通常為4或8 kB)獲得RAM。試圖訪問屬於另一個應用程序的頁面的應用程序被內核阻止,並受到嚴厲懲罰(“分段錯誤”,“一般保護錯誤” ...)。

當不再需要某個應用程序時一個頁面(尤其是在應用程序退出時),內核將​​控制該頁面並將其交給另一個進程。現代操作系統在將頁面退還之前先將其“空白”,其中“空白”表示“用零填充”。這樣可以防止數據從一個進程洩漏到另一個進程。請注意,Windows 95/98 / Millenium不會空白頁,可能會發生洩漏……但是這些操作系統是針對每台計算機的單個用戶使用的。

當然,有一些方法可以避免內核的憤怒:具有“足夠特權”(與上面特權不同的特權)的應用程序可以使用一些入口。在Linux系統上,這是 ptrace()。內核允許一個進程通過ptrace()讀寫另一個進程的內存,前提是兩個進程都在相同的用戶ID下運行,或者執行ptrace()的進程是“根”進程。 Windows中存在類似的功能。

最重要的是,RAM中的密碼並不比操作系統所允許的安全。根據定義,通過將一些機密數據存儲在內存中在一個過程中,您相信操作系統不會將其提供給第三方。操作系統是您的朋友,因為如果操作系統是敵人,那麼您將徹底迷失方向。


現在是最有趣的部分。由於操作系統強制執行流程分離,因此許多人試圖找到突破這些防禦的方法。他們發現了一些有趣的東西...

  • 應用程序看到的“ RAM”不一定是真正的“內存”。內核是一種幻覺的掌握者,它給出的頁面不一定存在。通過將RAM內容與磁盤上的專用空間交換來保持這種錯覺,在磁盤上存在大量可用空間。這稱為虛擬內存。應用程序不需要意識到這一點,因為內核會在需要時帶回頁面(但是,磁盤比RAM慢得多)。不幸的結果是,據稱保存在 RAM 中的某些數據將其保存到物理介質中,直到被覆蓋為止。特別是如果斷電,它將停留在該處。這允許攻擊者在壞人抓住機器並帶走機器的情況下進行攻擊,以便稍後檢查數據。否則,當一台計算機退役並在eBay上出售時,如果系統管理員忘記擦除磁盤內容,則可能會發生洩漏。

    Linux提供了一個名為 mlock()的系統,該系統可防止內核將某些特定的頁面發送到交換空間。由於將頁面鎖定在RAM中可能會耗盡其他過程可用的RAM資源,因此您需要一些特權(再次是root用戶)才能使用此功能。

    一種加劇的情況是,跟踪您的位置不一定很容易密碼確實在RAM中。作為程序員,您可以通過編程語言提供的抽象來訪問RAM。特別是,使用垃圾收集的編程語言可以透明地複制RAM中的對象(因為它確實對許多GC算法有幫助)。因此,大多數編程語言都會受到影響(例如Java,C#/。NET,Javascript,PHP,...幾乎是無止境的)。

  • 休眠帶回報復的相同問題。從本質上講,休眠方式必須將整個RAM寫入磁盤-這可能包括被鎖住的頁面,甚至包括CPU寄存器的內容。為了避免由於休眠而造成的洩漏,您必須採取諸如加密整個磁盤之類的嚴厲措施-這自然意味著在您喚醒計算機時都輸入了解鎖密碼。

  • 大型機模型假設它 可以運行彼此敵對的幾個進程,但仍保持完美的和平與孤立。現代硬件使這一點變得非常困難。當兩個進程在同一CPU上運行時,它們共享一些資源,包括緩存。緩存中的內存訪問比其他地方快得多,但是緩存的大小非常有限。這已被利用來從一個進程中恢復另一個進程所使用的加密密鑰。已開發出使用其他類似緩存的資源的變體,例如CPU中的分支預測。儘管對該主題的研究集中於加密密鑰,這是高價值秘密,但它實際上可以應用於任何數據。

    類似地,視頻卡可以進行直接內存訪問。是否可以濫用DMA來從其他進程讀取或寫入內存,取決於未記錄的硬件,閉源驅動程序和內核如何協作以實施適當的訪問控制。我不會打賭我的最後一件襯衫……


結論:是的,當您將密碼存儲在RAM中時,您信任該操作系統以保持機密性。是的,任務很艱鉅,在現代系統上幾乎是不可能的。如果某些數據是高度機密的,則您實際上不應該使用大型機模型,也不要允許潛在敵對實體在計算機上運行其代碼。

(順便說一下,這意味著託管虛擬機和雲計算不能最終保證安全。如果您對安全性很重視,請使用專用硬件。)

“虛擬機和雲計算最終不可能安全”。我一直對雲計算持懷疑態度。
還有一點要說明。在某個地方,在某個時間,在一定時間長度內,純文本僅*必須*駐留在“ RAM”中。如果純文本永遠不會暴露給任何人,則整個練習將變得毫無意義。結果是,表面上永遠不會持久保存並可以標記為“受保護”的RAM與在計算機系統範圍之內一樣安全。但是,您的觀點是,僅將內存(和相同的操作系統保護)視為安全的,因為根本不使用計算機。
為了最大程度地減少敏感數據以明文形式顯示,各種語言提供了包裝程序,使使用操作系統功能更容易防止分頁。參見例如[.Net SecureString](http://msdn.microsoft.com/zh-cn/library/system.security.securestring.aspx)。但是,這只能緩解問題,而不能解決問題。
關於休眠的注意事項-如果文件本身被加密(例如,在dm-crypt上交換),則存儲在其中的密碼也被加密-DMA-火線通常允許設備中的DMA訪問RAM(IOMMU會對此進行保護)。
我敢肯定,我已經知道所有這一切,但是您的回憶能力和解釋能力永遠不會給人留下深刻的印象,再次感謝托馬斯。
此外,如果您鬆開計算機,並且計算機仍處於開機狀態,則通過凍結內存芯片並讀取內容來恢復RAM的內容相對容易:http://www.zdnet.com/blog/security/cryogenically-frozen- ram繞過所有磁盤加密方法/ 900
有點相關,在創建緩衝區時不需要OpenGL清除幀緩衝區的內容,因此惡意程序有可能會抓住另一個程序正在繪製的內容,包括不可見緩衝區中的內容:http://stackoverflow.com/q / 4112421/309412
一個很好的總結。我僅提及的另一點是,儘管操作系統嘗試提供足夠的保護和服務以支持安全操作,但其他操作系統卻積極地嘗試尋找漏洞。加上程序員之間這種不同程度的理解,關心和能力,我們可以得出結論,沒有保證。與往常一樣,我們需要根據風險,可能性和後續影響進行評估,然後確定最佳/必要的措施。本文在提供有助於理解風險的基礎知識方面做得很好。可能性和影響將取決於具體情況。
這是一個有趣的答案。我要補充的是,大多數安全性都是一種錯覺-如果有人專門針對您,那麼您通常會被搞砸,而且通常不會破解加密或變得格外聰明-但老式的骯髒trick倆,例如通過觀看別人的密碼來竊取別人的密碼。
我想指出的是,至少在Linux上,“ mlock”不需要root priv。但是,如果您不是root用戶,則可以鎖定多少內存有嚴格的限制。
除了大型機,還有什麼其他型號?
回复:“操作系統是您的朋友,因為如果操作系統是敵人,那麼您就完全輸了。”很好地說明了操作系統如何與您抗衡,以及如果發生這種情況該怎麼辦,請參閱[馬修·加勒特(Matthew Garrett)的《 LibrePlanet 2013演講》(http://media.libreplanet.org/u/libby/m/embracing-secure-boot-and-rejecting-restricted-boot-matthew-garrett/)大約7十五秒。
您已經涵蓋了幾乎所有角度,但是您沒有提到寄存器始終都保存在堆棧中,並且當發生上下文或線程切換時,所有寄存器又再次轉儲到內存中。因此,在寄存器中保持機密也不會保存。
-1
user2213
2013-01-15 02:29:04 UTC
view on stackexchange narkive permalink

我認為操作系統可以完成他的工作,並避免進程訪問其他人分配的內存。但是我認為這是可行的。

是的,可以訪問另一個進程的內存。在Windows上,這等於具有 SE_DEBUG_PRIVILEGE 並使用 ReadProcessMemory()來提取所需的信息。

您可以從Windows驅動程序執行相同的操作,儘管由於當前內存分頁到下半部分會有些複雜,因此很難正確使用。

無論哪種情況,您都需要具有訪問權限一個管理帳戶,一個錯誤分配了 SE_DEBUG_PRIVILEGE 的進程,或一個具有這種特權的,可以被說服做您所需的特權的進程。

因此,歸結為確保沒有人可以升級以獲得這些特權。實際上,我們確保只有受信任的用戶才能擁有這些特權。如果您有權訪問管理帳戶,則可以很容易地從另一個帳戶的進程的內存中直接讀取密碼。

在Linux下,您可以使用 ptrace( ) PTRACE_PEEK_DATA 選項。

您可能會問為什麼這些功能首先存在?實際上,它們在調試過程中非常方便。可以想像,這是管理員用戶可能希望做的事情。相比之下,普通用戶則不需要,而且應該彼此隔離。

這就是為什麼人們建議一段時間以來,以Administrator帳戶運行所有內容通常不是一個好主意的原因。 / p>

感謝您對Windows和GNU / Linux的簡潔解釋(我想對於其他Unix系統也是如此)。
@AntoinePinsard是的,如果他們實現`ptrace`,則很有可能!
如果沒有特殊權限,則在勝利時您可以讀取在同一用戶上運行的其他進程的內存。
@Code是真的。我不確定任何操作系統都能防禦您的攻擊!
-1
bob_dvb
2013-03-18 15:15:39 UTC
view on stackexchange narkive permalink

我在消費電子領域工作,這裡的安全性與服務器環境有些不同。在這裡,我們必須假設該產品處於敵對環境中。因此,出於訂戶管理的目的,密鑰是安全的。第一道防線是SoC具有隱藏的寄存器,即使操作系統實際上也無法訪問這些寄存器,它們在製造時就被燒壞了,並且熔斷了保險絲以阻止訪問。同樣,我們自己也看不到密鑰,因為這在生產現場是不安全的,相反,它們被預先包裝了一個我們不知道的批量密鑰,只有芯片供應商和創建密鑰的人才知道(主可以在芯片中使用後銷毀密鑰)。一旦芯片上裝有機密信息,就可以將其鎖定,並且永遠不會*被解鎖。

如果您無法訪問密鑰,那麼如何解密內容呢?通過SoC上的加密協處理器,您可以加載密鑰位置,而無需實際知道其中的值。您也永遠不會看到加密處理器的微代碼,因為即使在製造時,您也無法注入任何東西。

如果您的密鑰或證書不適合大量的芯片寄存器,則必須將它們存儲在RAM和/或 NVM中,但是由於使用了加密處理器您無需公開這些值。 RAM或NVM本身可以用芯片來加密,而密鑰本身並不為人所知。

與計算機不同,安全嵌入式系統還具有一定的物理安全性。 RAM連接軌道不允許位於PCB表面(“埋孔”)。這是因為,如果RAM中有明確的元素,則需要限制訪問,則可以減慢或凍結CPU,然後探測RAM。

最後,對於智能卡而言,可以攔截SoC和卡之間的交易。這就是所謂的“卡共享”,解決方案是對卡和SoC之間的交易進行加密,並將它們彼此綁定,以使它們無法交換或共享。

我知道DRM / content安全對於Internet上的某些人來說並不受歡迎,但是我想我會分享來自具有某些特定安全要求的行業的一些高級概念。

*理論上。

+1。您知道現代筆記本電腦/台式計算機是否已在做類似的事情嗎?我敢打賭至少有幾個行業(認為軍事,政府)會對獲得這種級別的安全性感興趣。還是必須是完全定制的電子設備?
從理論上講,Microsoft對EFI引導進行的最新更改可以被Linux用於建立信任鏈,正如@mricon所說,SElinux在其他地方也可以提供幫助。我也一直在考慮OKL4的高安全性,因為您可以將Linux之外的安全組件帶到另一個OS。
可能感興趣的@mjuarez,:[降低TPM芯片數](https://duckduckgo.com/html?q=decapping%20TPM%20chips)。
mricon
2013-01-15 02:44:21 UTC
view on stackexchange narkive permalink

在Linux平台上正在進行一些工作,以禁止超級用戶訪問正在運行的進程的內存。使用SELinux,您可以從Fedora 17開始: SELinux Deny Ptrace

Giffyguy
2013-01-15 01:33:30 UTC
view on stackexchange narkive permalink

您使用的是哪種語言/平台?

如果是.NET,請檢出 PasswordBox控件和 SecureString類。

SecureString類表示一種將密碼存儲在內存中而不讓任何人都可以訪問的方法,即使是偷偷窺視應用程序內存的黑客也是如此。包含SecureString,因此您可以確保端到端的密碼安全。

請不要僅僅發布鏈接作為您的答案。盡力闡述您的答案,然後才將鏈接發佈為來源/信用。如果鏈接不見了,您的答案也將如此。
我同意@Lorenzo +1。我有一種習慣,就是將自己的答案進行一系列修改,而不是一口氣把它全部搞清楚。儘管我不擔心MSDN鏈接很快就會消失。 :)
@Giffyguy-出於多種原因在.NET中使用`SecureString`是有意義的,但並不能防止*複雜的“偷窺您的應用程序內存的黑客”獲得密碼;它雖然增加了混淆。 SecureStrings將在內存中加密;但是,解密密鑰也必定在內存中。但這仍然比內存中的純文本pw好,因此它從未在coredump / swapfile / etc中公開。
@dr jimbob +1是,儘管入侵.NET通常是徒勞的。每當出現安全漏洞時,MS通常都會在幾週左右的時間內發布補丁來阻止它。
`SecureString`的收益非常有限。這是針對崩潰轉儲和交換文件的。它不能防止惡意程序訪問您的進程內存。這些能夠獲取密碼的應用程序不是安全漏洞,MS不會對其進行修補。
@CodesInChaos-確實如此。 SecureString使用[數據保護API](http://en.wikipedia.org/wiki/Data_Protection_API);在2010年進行了反向工程(不確定自那時以來MS是否已更改)。破解並不容易(例如,如果您擁有對系統的完全訪問權限;在使用鍵盤記錄器敲擊SecureString之前捕獲密碼就更容易了)。但是,由於正在運行的應用程序必須能夠對其進行解密,因此,複雜的分析(具有對磁盤/內存的完全訪問權限)必須能夠恢復它。
petertonoli
2013-03-18 16:08:13 UTC
view on stackexchange narkive permalink

否,不應將以明文形式存儲在RAM中的密碼視為安全密碼。通常,在具有直接訪問接口(例如FireWire,ExpressCard和Thunderbolt)的x86和x86-64體系結構上,這些接口可用於繞過操作系統內存保護,從而從內存中獲取純文本密碼。

使用FireWire獲得純文本密碼並非只是理論上的攻擊。現在正在出售軟件以獲取BitLocker,PGP和TrueCrypt加密磁盤的純文本密碼 ElcomSoft解密BitLocker,PGP和TrueCrypt容器

security.stackexchange上有一個單獨的線程如何緩解DMA基本攻擊在Linux下安全禁用火線/雷電,修補DMA暴露。微軟也有一個知識庫文章,以緩解通過BitLocker上的Firewire和Thunderbolt進行的攻擊阻止SBP-2驅動程序和Thunderbolt控制器以減少對BitLocker的1394 DMA和Thunderbolt DMA威脅

更多有關此攻擊的詳細信息,請參見Wikipedia DMA攻擊

Dan Is Fiddling By Firelight
2013-01-15 04:09:51 UTC
view on stackexchange narkive permalink

除了所有利用操作系統漏洞的軟件攻擊之外,如果攻擊者可以物理訪問您的計算機,他們還可以直接從內存中讀取密鑰。

冷的影響如何產生引導攻擊被最小化了?

“如果攻擊者可以物理訪問您的計算機”,那麼通常幾乎所有的賭注都被認為是無效的,並且攻擊者能夠從內存中的變量中讀取密碼的能力通常是最少的問題。
防止冷啟動攻擊的一種可能的保護措施是加密技術,該技術可加密RAM的內容,並且僅將CPU寄存器用作“受信任”位置來存儲加密密鑰。簽出例如
Kaz
2013-01-15 04:59:11 UTC
view on stackexchange narkive permalink

您提出了一個有效的問題,而實際上,這通常在與安全性相關的軟件中得到解決。當不再需要諸如密鑰之類的敏感對象時,某些程序將不會簡單地將內存交還給內存管理庫或操作系統,而是先通過覆蓋敏感位來消除它們。

當然,有些程序需要持續按住鍵。例如 ssh-agent 。因此,這些程序容易受到攻擊。如果您是多用戶計算機上的普通用戶,則 ssh-agent 的動態內存將受到具有root privs並且可以查看計算機內存任何部分的任何人的攻擊。

無論如何,即使短暫使用鍵的程序仍然存在漏洞窗口。一微秒可能是CPU時間的永恆。惡意的超級用戶甚至可以在某些指令上無限期地暫停程序,而該程序在內存中的某處具有純文本格式的敏感數據。

因此,根據經驗,不要執行任何對安全性敏感的操作在計算機上進行計算(如果該計算機具有您不信任的任何用戶或軟件)以及不信任的操作系統,以防止這些用戶或軟件提升其特權,以便他們可以窺視您的密鑰或明文數據。

使用任何安全客戶端時,您都信任該程序以及它的整個平台,直到整個硬件平台以及預安裝或以後安裝的每個程序中的每條機器指令為止。

(所謂的“可信計算”並不能解決這個問題;它只是改變了惡棍的身份。)

+1所謂的“可信計算”不能解決此問題;只會改變小人是誰
既然如此,那麼如何實現所有基於軟件的drm?(可播放時間<3.0,寬屏電視,黃金時段等)
Vivek Sethi
2013-01-17 20:56:09 UTC
view on stackexchange narkive permalink

即使密鑰是加密的,鱈魚啟動攻擊也可以檢索您的密碼:查看此正在進行的冷啟動攻擊的視頻。. http://www.youtube.com/watch?v=JDaicPIgn9U

cxx6xxc
2013-01-18 17:06:29 UTC
view on stackexchange narkive permalink

除非您有時間閱讀所有源代碼並確認不存在漏洞利用程序,否則一定要有一定程度的信任才能保證操作系統和應用程序運行的安全性。如果您有那個時間,就不需要信任。但這是不可能的。如果可能的話,最好在一台機器上運行專有項目,並在另一台機器上運行所有必須信任的內容。與基於信仰的解決方案相比,物理隔離可以很好地解決問題。

你是絕對正確的。這就是為什麼我(或至少嘗試)僅在計算機上運行自由軟件的原因。
您能否詳細說明為什麼操作系統和應用程序之間必須有任何信任?我認為,從理論上講,通過足夠的沙箱操作(root監獄,有限權限等),應該可以安全地運行病毒。我並不是說這是實用的或100%安全的,但是應該可以完全沙漏不受信任的應用程序。
@Luc可以肯定,但這完全與沙盒無關。您沒有在沙盒中運行日常任務,對嗎?
@Kaii如果我從事某些重要工作,則可以選擇。
Nakedible
2013-03-18 12:59:13 UTC
view on stackexchange narkive permalink

需要做一些相關的研究,以確保即使超級用戶也無法訪問存儲在某些其他進程的內存中的機密。我從未真正完成過這項工作,因此這只是一個起點。這並不能阻止任何物理攻擊,例如冷啟動攻擊。

在Linux上從根目錄保留機密

gimix
2013-03-15 13:29:38 UTC
view on stackexchange narkive permalink

這不能解決您的問題,儘管您可以使用一種技巧來最大程度地減少將密碼或其他機密存儲在內存中的時間,然後再將其清零。

請小心使用一種保證您正在寫入相同的內存,而不是分配具有不同值的新對象。例如,在Java中,您可以使用 byte [] 而不是 String 來保存秘密。

我在讀這篇文章,在想類似的東西。如果需要將其存儲在RAM中,那段時間不能對密碼進行加密嗎?我知道它必須以純文本形式存在,但是可以將其最小化。
Charles Munger
2013-03-18 14:26:37 UTC
view on stackexchange narkive permalink

鑑於這可能適用於具有不同保護級別的許多操作系統,請記住以下幾點:

  1. 無論如何,您都無法阻止密碼被盜在某個時候在內存中。如果有人可以實時訪問應用程序的內存,則無法阻止他們查看它。

  2. 密碼通常比受保護的密碼更有價值-用戶重用密碼,並且通過接受密碼登錄,即使密碼保護的數據遭到破壞,您也要承擔一定程度的保密密碼責任。通過使用慢速散列函數(PBKDF,scrypt,bcrypt)對用戶密碼進行散列並使用散列進行身份驗證,可以在某種程度上減輕對冷存儲器(液氮或休眠)的攻擊所造成的損害。

  3. 從內存中清除用戶密碼是一種好習慣。正確執行此操作涉及許多陷阱,因此請確保使用適當的庫: Windows Linux示例

  4. ol>


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...