瀏覽器是如何存儲密碼的?

0 評論 9790 瀏覽 0 收藏 16 分鐘

一、引言

我曾經(jīng)介紹過名為dumpmon的推特機器人,它監(jiān)控著眾多“貼碼網(wǎng)站”的賬戶轉儲、配置文件和其他信息。自那以后,我一直留意著監(jiān)測到的信息。接下來會有關于dumpmon的一系列文章,而本文則關注瀏覽器是如何存儲密碼的。

這里提到dumpmon,是因為我偶然發(fā)現(xiàn)一些貼碼,比如這篇,應該是感染在計算機上的惡意軟件的日志。我便想:我總是認為最好不要讓瀏覽器直接存儲密碼,但是原因呢?惡意軟件從感染的計算機中獲得密碼會有多輕松呢?因為從一處獲得所有想要的資料有點困難,所以我決定在此文貼出結果以及一些從各個瀏覽器的密碼管理器中提取密碼的簡單代碼。

本文所述是在windows 8系統(tǒng)上分析下述瀏覽器。

二、Chrome瀏覽器

獲得密碼難易程度:簡單

我們從Chrome瀏覽器開始。令人失望的是,chrome瀏覽器是最容易被提取密碼的。加密后的密鑰存儲于%APPDATA%\..\Local\Google\Chrome\User Data\Default\Login Data”下的一個SQLite數(shù)據(jù)庫中。但是是如何獲轉存并加密的呢?我從《谷歌Chrome瀏覽器是如何存儲密碼的》這篇文章中獲得了Chrome存儲密碼的諸多信息,而這篇文章是4年前寫得。雖然從那篇文章以后Chrome做了些改變,但是我將按照同樣的方式,利用Chromium源碼的一些片段向你展示密碼是如何轉儲的。

存儲加密密碼

當用戶訪問網(wǎng)站時,Chrome會首先判斷此次登陸是否是一次成功的登錄,判斷代碼片段:

瀏覽器是如何存儲密碼的?

如果成功登錄,并且使用的是一套新的證書,這個證書是瀏覽器之前沒有生成過的,Chrome就會生成一個提示條,詢問用戶是否需要記住密碼:

瀏覽器是如何存儲密碼的?

在此為節(jié)省篇幅,我省略了創(chuàng)建提示條的代碼。當點擊“保存密碼”時,就會調用Chrome密碼管理器的“保存”函數(shù)來響應操作:

瀏覽器是如何存儲密碼的?

簡單吧。如果是一次新的會話登錄,就以如下代碼執(zhí)行保存:

瀏覽器是如何存儲密碼的?

再次為控制篇幅,裁剪了一些內容(例如一個對證書是否屬于google的網(wǎng)站的操作審查等等)。在這函數(shù)被調用之后,執(zhí)行AddLoginImpl()函數(shù)的任務被調用。這是用來使界面快速響應的:

瀏覽器是如何存儲密碼的?

該函數(shù)會調用登陸數(shù)據(jù)庫對象的AddLogin()函數(shù),以檢查其操作是否成功。下面就是AddLogin()(我保證,我們馬上就要看到密碼是如何存儲的了):

瀏覽器是如何存儲密碼的?

這里有些有趣的東西。我們利用用戶密碼生成一個字符串密鑰。這段代碼已經(jīng)減掉了,但是”sql:Statement”行下面,執(zhí)行了一個SQL查詢語句,實現(xiàn)了在登錄數(shù)據(jù)文件中存儲加密數(shù)據(jù)。該EncryptedString函數(shù)僅僅是在一個加密對象上簡單調用了EncryptString16函數(shù)(就是下面這個):

瀏覽器是如何存儲密碼的?

最終,我們看到密碼是調用Windows API函數(shù)CryptProtectData來加密的。這意味著,只有用加密時使用的登陸證書,密碼才能被恢復。而這根本不是問題,惡意軟件通常就是在用戶登陸環(huán)境下執(zhí)行的。

密碼破譯

在討論如何破譯上面存儲的密碼之前,讓我們首先使用Sqlite瀏覽器來查看一下登陸文件中的數(shù)據(jù):

瀏覽器是如何存儲密碼的?

我們的目的是從這個數(shù)據(jù)庫中抽取出action_url,username_value和password_value(是二進制數(shù)據(jù),所以SQLite瀏覽器不能顯示)。而破解密碼,只需要調用Windows API中的CryptUnprotectData函數(shù)。幸運地是,Python為調用Windows API準備了一個完美的叫做pywin32的庫。

先看一下我們使用的PoC:

運行上述代碼,可以看到已經(jīng)成功了!

瀏覽器是如何存儲密碼的?

雖然找到密碼是如何存儲的有點費事(也可以使用其他的動態(tài)方法,但是分析代碼會更透徹),但是解密密碼則幾乎沒費什么力氣。唯一被保護起來的就是密碼的部分,還僅僅保護當前用戶。

 

2/4

 

三、IE瀏覽器?

獲得密碼難易程度:簡單/一般/困難(依版本而定)

本質上來講,直到IE10之前,IE瀏覽器的密碼管理與Chrome使用的是相同的技術,但有一些有趣的改變。為了全面的展示,我們先簡單討論一下IE7——IE9的密碼存儲,然后再討論在IE10中的變革。

IE7-9瀏覽器

在IE的早期版本中,根據(jù)密碼類型的不同,會被存儲于兩個不同的地方:

注冊表(基于表單的驗證)——這類密碼是提交給諸如Facebook、Gmail之類站點的。

證書文件——HTTP驗證密碼方式,類似于網(wǎng)上登陸證書。

根據(jù)本篇文章需要,接下來討論基于表單驗證的證書,這也是大多數(shù)攻擊者可能選擇的攻擊目標。這些證書存儲于如下注冊表鍵位置:

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2

用regedit(注冊表編輯器)可以看到值,類似于下面這樣:

瀏覽器是如何存儲密碼的?

正如Chrome中的示例,這些證書使用Windows API中的CryptProtectData函數(shù)加密后儲存。不同之處是該函數(shù)添加了額外的熵(譯者注:熵,熵就是混亂的程度,用來描述某個事件不斷趨向混亂的過程)。這里的熵,就是這注冊表鍵值,它是網(wǎng)站URL的SHA1的校驗和,以供證書使用。

這非常有用,因為當用戶訪問網(wǎng)站時,IE能夠迅速根據(jù)URL的哈希值判斷是否已經(jīng)有此證書,之后再用此哈希值完成證書解密。如果攻擊者不知道此處使用了URL,解密證書就會變得很困難。

通常,攻擊者能夠通過歷遍用戶因特網(wǎng)訪問歷史,hash每個URL以及檢查每個存儲證書的方式,來降低此種保護方式的效果。

本文中沒有貼出完整代碼,你可以在這里處獲得完整示例?,F(xiàn)在,我們開始討論IE10。

 

3/4

 

IE10瀏覽器

IE10改變了密碼存儲方式。所有自動填充的密碼存儲于證書管理中一個叫“web證書”的地方,如下圖所示:

瀏覽器是如何存儲密碼的?

個人理解(在這個問題上我找不到更多的信息),這些證書文件存放于%APPDATA%\Local\Microsoft\Vault\[random]目錄下。關于這些文件是什么及其所用格式,可以在這里找到。

我所知道的是獲得這些密碼并不難。事實上,非常容易。為了支持windows的應用商店,微軟提供了一個新的Windows runtime,用來支持更多地API訪問。該winRT提供了對Windows.Security.Credentials namespace的訪問接口,它提供了用來遍歷用戶證書的所有函數(shù)。

事實上,這有一個簡短的C#腳本PoC,在用戶的環(huán)境下執(zhí)行時,它會檢索存儲的密碼:

瀏覽器是如何存儲密碼的?

執(zhí)行該程序后,輸出類似于下圖所示:

瀏覽器是如何存儲密碼的?

注意:我刪除了一些我已經(jīng)禁止IE儲存的站點。除此之外,我也不是很清楚為什么有些憑據(jù)被儲存了起來。

正如你所見,只要我們的程序在特定用戶環(huán)境中執(zhí)行,提取指定用戶使用的所有密碼略繁瑣但還是挺簡單的。下面我們繼續(xù)。

 

4/4

 

四、Firefox瀏覽器

獲得密碼的難易程度:一般/非常困難

接下來談談比較棘手的Firefox。主要使用這些幻燈片中的方法獲取關于用戶數(shù)據(jù)存儲位置的資料。

首先,透露下Firefox的密碼管理的小秘密。為滿足開發(fā)者創(chuàng)建滿足各種安全標準的應用程序,Mozilla開發(fā)了一個叫做“Network Security Services”,或叫NSS的開源庫。Firefox使用其中一個叫做”Security Decoder Ring”,或叫SDR的API來幫助實現(xiàn)賬號證書的加密和解密函數(shù)。雖然名字很文藝,我們還是來看看firefox是如何使用它完成加密的:

當一個Firefox配置文件被首次創(chuàng)建時,一個叫做SDR的隨機key和一個Salt(譯者注:Salt,在密碼學中,是指通過在密碼任意固定位置插入特定的字符串,讓散列后的結果和使用原始密碼的散列結果不相符,這種過程稱之為“加鹽”)就會被創(chuàng)建并存儲在一個名為“key3.db”的文件中。利用這個key和鹽,使用3DES加密算法來加密用戶名和密碼。密文是Base64編碼的,并存儲在一個叫做signons.sqlite的sqlite數(shù)據(jù)庫中。Signons.sqlite和key3.db文件均位于%APPDATA%\Mozilla\Firefox\Profiles\[random_profile]目錄。

所以我們要做的就是得到SDR密鑰。正如此處解釋的,這個key被保存在一個叫PCKS#11軟件“令牌”的容器中。該令牌被封裝進入內部編號為PKCS#11的“槽位”中。因此需要訪問該槽位來破譯賬戶證書。

還有一個問題,這個SDR也是用3DES(DES-EDE-CBC)算法加密的。解密密鑰是Mozilla叫做“主密碼”的hash值,以及一個位于key3.db文件中對應的叫做“全局鹽”的值。

Firefox用戶可以在瀏覽器的設置中設定主密碼,但關鍵是好多用戶不知道這個特性。正如我們看到的,用戶整個賬號證書的完整性鏈條依賴于安全設置中選擇的密碼,它是攻擊者唯一不知道的值。如果用戶使用一個強健的主密碼,那么攻擊者想要恢復存儲的證書是不太可能的。

那么——如果用戶沒有設置主密碼,空密碼就會被使用。這意味著攻擊者可以提取全局鹽,獲得它與空密碼做hash運算結果,然后使用該結果破譯SDR密鑰。再用破譯的SDR密鑰危害用戶證書。

該過程看起來就是這樣:

瀏覽器是如何存儲密碼的?

想知道的更清楚,我們可以簡單查下源代碼。負責證書解密的主要函數(shù)是PK11SDR_Decrypt。此處不再展示整個函數(shù),僅分別列出如下被調用的函數(shù):

PK11_GetInternalKeySlot() //得到內部key槽

PK11_Authenticate() //使用主密碼對slot鑒權

PK11_FindFixedKey() //從slot中獲得SDR密鑰

Pk11_Decrypt() //使用SDR密鑰破譯Base64編碼的數(shù)據(jù)

至于破譯密碼的示例代碼,過程有點復雜,此處就不再累述了。介紹兩個可以完成此過程的開源工程:

FireMaster – 暴力破解主密碼

ffpasscrack – 推薦的是Python的解決方案。這個方案使用libnss.so庫做負載DLL。在Windows上使用的話,可以利用cygwin的DLL文件。

五、總結

希望此文能讓你清楚的了解到瀏覽器是如何存儲密碼的,以及為何在一些情況下不該讓它們存儲。但是,本文不能下這樣的論斷,即瀏覽器存儲密碼一點都不安全。例如,在Firefox瀏覽器案例中,如果采用高強度的主密碼,賬號的細節(jié)資料是非常難獲取的。

若是采用別的密碼管理,比如LastPass、KeePass,則是極好的方案,也可以借助設備采用雙因素認證,比如Yubkey。

來源:51CTO

更多精彩內容,請關注人人都是產品經(jīng)理微信公眾號或下載App
評論
評論請登錄
  1. 目前還沒評論,等你發(fā)揮!