瀏覽器是如何存儲(chǔ)密碼的?

0 評(píng)論 9846 瀏覽 0 收藏 16 分鐘

一、引言

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

這里提到dumpmon,是因?yàn)槲遗既话l(fā)現(xiàn)一些貼碼,比如這篇,應(yīng)該是感染在計(jì)算機(jī)上的惡意軟件的日志。我便想:我總是認(rèn)為最好不要讓瀏覽器直接存儲(chǔ)密碼,但是原因呢?惡意軟件從感染的計(jì)算機(jī)中獲得密碼會(huì)有多輕松呢?因?yàn)閺囊惶帿@得所有想要的資料有點(diǎn)困難,所以我決定在此文貼出結(jié)果以及一些從各個(gè)瀏覽器的密碼管理器中提取密碼的簡(jiǎn)單代碼。

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

二、Chrome瀏覽器

獲得密碼難易程度:簡(jiǎn)單

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

存儲(chǔ)加密密碼

當(dāng)用戶(hù)訪(fǎng)問(wèn)網(wǎng)站時(shí),Chrome會(huì)首先判斷此次登陸是否是一次成功的登錄,判斷代碼片段:

瀏覽器是如何存儲(chǔ)密碼的?

如果成功登錄,并且使用的是一套新的證書(shū),這個(gè)證書(shū)是瀏覽器之前沒(méi)有生成過(guò)的,Chrome就會(huì)生成一個(gè)提示條,詢(xún)問(wèn)用戶(hù)是否需要記住密碼:

瀏覽器是如何存儲(chǔ)密碼的?

在此為節(jié)省篇幅,我省略了創(chuàng)建提示條的代碼。當(dāng)點(diǎn)擊“保存密碼”時(shí),就會(huì)調(diào)用Chrome密碼管理器的“保存”函數(shù)來(lái)響應(yīng)操作:

瀏覽器是如何存儲(chǔ)密碼的?

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

瀏覽器是如何存儲(chǔ)密碼的?

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

瀏覽器是如何存儲(chǔ)密碼的?

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

瀏覽器是如何存儲(chǔ)密碼的?

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

瀏覽器是如何存儲(chǔ)密碼的?

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

密碼破譯

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

瀏覽器是如何存儲(chǔ)密碼的?

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

先看一下我們使用的PoC:

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

瀏覽器是如何存儲(chǔ)密碼的?

雖然找到密碼是如何存儲(chǔ)的有點(diǎn)費(fèi)事(也可以使用其他的動(dòng)態(tài)方法,但是分析代碼會(huì)更透徹),但是解密密碼則幾乎沒(méi)費(fèi)什么力氣。唯一被保護(hù)起來(lái)的就是密碼的部分,還僅僅保護(hù)當(dāng)前用戶(hù)。

 

2/4

 

三、IE瀏覽器?

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

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

IE7-9瀏覽器

在IE的早期版本中,根據(jù)密碼類(lèi)型的不同,會(huì)被存儲(chǔ)于兩個(gè)不同的地方:

注冊(cè)表(基于表單的驗(yàn)證)——這類(lèi)密碼是提交給諸如Facebook、Gmail之類(lèi)站點(diǎn)的。

證書(shū)文件——HTTP驗(yàn)證密碼方式,類(lèi)似于網(wǎng)上登陸證書(shū)。

根據(jù)本篇文章需要,接下來(lái)討論基于表單驗(yàn)證的證書(shū),這也是大多數(shù)攻擊者可能選擇的攻擊目標(biāo)。這些證書(shū)存儲(chǔ)于如下注冊(cè)表鍵位置:

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

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

瀏覽器是如何存儲(chǔ)密碼的?

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

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

通常,攻擊者能夠通過(guò)歷遍用戶(hù)因特網(wǎng)訪(fǎng)問(wèn)歷史,hash每個(gè)URL以及檢查每個(gè)存儲(chǔ)證書(shū)的方式,來(lái)降低此種保護(hù)方式的效果。

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

 

3/4

 

IE10瀏覽器

IE10改變了密碼存儲(chǔ)方式。所有自動(dòng)填充的密碼存儲(chǔ)于證書(shū)管理中一個(gè)叫“web證書(shū)”的地方,如下圖所示:

瀏覽器是如何存儲(chǔ)密碼的?

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

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

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

瀏覽器是如何存儲(chǔ)密碼的?

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

瀏覽器是如何存儲(chǔ)密碼的?

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

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

 

4/4

 

四、Firefox瀏覽器

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

接下來(lái)談?wù)劚容^棘手的Firefox。主要使用這些幻燈片中的方法獲取關(guān)于用戶(hù)數(shù)據(jù)存儲(chǔ)位置的資料。

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

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

所以我們要做的就是得到SDR密鑰。正如此處解釋的,這個(gè)key被保存在一個(gè)叫PCKS#11軟件“令牌”的容器中。該令牌被封裝進(jìn)入內(nèi)部編號(hào)為PKCS#11的“槽位”中。因此需要訪(fǎng)問(wèn)該槽位來(lái)破譯賬戶(hù)證書(shū)。

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

Firefox用戶(hù)可以在瀏覽器的設(shè)置中設(shè)定主密碼,但關(guān)鍵是好多用戶(hù)不知道這個(gè)特性。正如我們看到的,用戶(hù)整個(gè)賬號(hào)證書(shū)的完整性鏈條依賴(lài)于安全設(shè)置中選擇的密碼,它是攻擊者唯一不知道的值。如果用戶(hù)使用一個(gè)強(qiáng)健的主密碼,那么攻擊者想要恢復(fù)存儲(chǔ)的證書(shū)是不太可能的。

那么——如果用戶(hù)沒(méi)有設(shè)置主密碼,空密碼就會(huì)被使用。這意味著攻擊者可以提取全局鹽,獲得它與空密碼做hash運(yùn)算結(jié)果,然后使用該結(jié)果破譯SDR密鑰。再用破譯的SDR密鑰危害用戶(hù)證書(shū)。

該過(guò)程看起來(lái)就是這樣:

瀏覽器是如何存儲(chǔ)密碼的?

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

PK11_GetInternalKeySlot() //得到內(nèi)部key槽

PK11_Authenticate() //使用主密碼對(duì)slot鑒權(quán)

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

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

至于破譯密碼的示例代碼,過(guò)程有點(diǎn)復(fù)雜,此處就不再累述了。介紹兩個(gè)可以完成此過(guò)程的開(kāi)源工程:

FireMaster – 暴力破解主密碼

ffpasscrack – 推薦的是Python的解決方案。這個(gè)方案使用libnss.so庫(kù)做負(fù)載DLL。在Windows上使用的話(huà),可以利用cygwin的DLL文件。

五、總結(jié)

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

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

來(lái)源:51CTO

更多精彩內(nèi)容,請(qǐng)關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號(hào)或下載App
評(píng)論
評(píng)論請(qǐng)登錄
  1. 目前還沒(méi)評(píng)論,等你發(fā)揮!