明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

安全科普:瀏覽器保存密碼原理及密碼查看 編寫(xiě)后門(mén)取得密碼

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

 一、引言

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

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

http://pastebin.com/raw.php?i=QMzNWqPF

二、瀏覽器

本文所述,是在windows 8系統(tǒng)上分析下述瀏覽器,此處鏈接列表是為了幫助讀者直接跳到感興趣的瀏覽器部分:

    Chrome 27.0.1453.110
    IE 10
    Firefox 21.0

chrome

三、Chrome瀏覽器

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

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

    存儲(chǔ)加密密碼

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

chrome_step1

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

chrome_2

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

chrome_step4

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

chrome_step5

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

chrome_step7

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

chrome_step8

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

chrome_step10

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

    密碼破譯

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

chrome_db

我們的目的是從這個(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:

from os import getenv
import sqlite3
import win32crypt
 
# Connect to the Database
conn = sqlite3.connect(getenv("APPDATA") + "..LocalGoogleChromeUser DataDefaultLogin Data")
cursor = conn.cursor()
# Get the results
cursor.execute('SELECT action_url, username_value, password_value FROM logins')
for result in cursor.fetchall():
 
# Decrypt the Password
    password = win32crypt.CryptUnprotectData(result[2], None, None, None, 0)[1]
    if password:
        print 'Site: ' + result[0]
        print 'Username: ' + result[1]
        print 'Password: ' + password

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

chrome_success

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

四、IE瀏覽器

ie10

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

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

    IE7-9瀏覽器

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

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

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

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

HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerIntelliFormsStorage2

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

ie_reg

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

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

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

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

    IE10瀏覽器

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

ie_web_3

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

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

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


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.Credentials;
 
namespace PasswordVaultTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a handle to the Widnows Password vault
            Windows.Security.Credentials.PasswordVault vault = new PasswordVault();
            // Retrieve all the credentials from the vault
            IReadOnlyList credentials = vault.RetrieveAll();
            // The list returned is an IReadOnlyList, so there is no enumerator.
            // No problem, we'll just see how many credentials there are and do it the
            // old fashioned way
            for (int i = 0; i < credentials.Count; i++)
            {
                // Obtain the credential
                PasswordCredential cred = credentials.ElementAt(i);
                // "Fill in the password" (I wish I knew more about what this was doing)
                cred.RetrievePassword();
                // Print the result
                Console.WriteLine(cred.Resource + ':' + cred.UserName + ':' + cred.Password);
            }
            Console.ReadKey();
        }
    }
}


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

ie_4

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

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

五、Firefox瀏覽器

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

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

首先,透露下Firefox的密碼管理的小秘密。為滿足開(kāi)發(fā)者創(chuàng)建滿足各種安全標(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ò)程稱之為“加鹽”)就會(huì)被創(chuàng)建并存儲(chǔ)在一個(gè)名為“key3.db”的文件中。利用這個(gè)key和鹽,使用3DES加密算法來(lái)加密用戶名和密碼。密文是Base64編碼的,并存儲(chǔ)在一個(gè)叫做signons.sqlite的sqlite數(shù)據(jù)庫(kù)中。Signons.sqlite和key3.db文件均位于%APPDATA%MozillaFirefoxProfiles[random_profile]目錄。

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

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

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

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

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

QQ截圖20130719165845

想知道的更清楚,我們可以簡(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上使用的話,可以利用cygwin的DLL文件。

六、總結(jié)

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

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

(全文完)


上面是電腦上網(wǎng)安全的一些基礎(chǔ)常識(shí),學(xué)習(xí)了安全知識(shí),幾乎可以讓你免費(fèi)電腦中毒的煩擾。