Daviid
Daviid

Reputation: 1586

Can I export cookies from python to Chrome?

Here's what I'm trying to do. I want to read the cookies from Chrome's sqlite file, use them on python and then save them again to Chrome's sqlite file since they could have been updated while using them with python.

This is more or less the code I have to test this, I can extract them and use them correctly but I can't manage to update them on sqlite and keep using them on the browser.

I'm not even sure if I'm using the correct types or if I'm passing the correct type to the UPDATE, should I do anything to newEncrypted before passing it to sqlite?

Upvotes: 2

Views: 2187

Answers (1)

CristiFati
CristiFati

Reputation: 41116

sqlite documentation page: [Python]: sqlite3 - DB-API 2.0 interface for SQLite databases.

code.py:

import sys
import sqlite3
import win32crypt


COOKIE_FILE = "ChromeCookies.db"
HOST_KEYS = ".google.com", "www.google.com"


def decrypt_cookies(query_result):
    cookies = []
    for host_key, name, value, expires_utc, encrypted in query_result:
        if encrypted:
            decrypted_descr, decrypted = win32crypt.CryptUnprotectData(encrypted, None, None, None, 0)
        else:
            decrypted_descr, decrypted = u"", u""
        cookies.append((host_key, name, expires_utc, decrypted, decrypted_descr, value))
        # Idx:              0       1        2           3            4            5
    return cookies


def init_db(file_name=COOKIE_FILE):
    conn = sqlite3.connect(file_name)
    return conn, conn.cursor()


def shutdown_db(cursor, connection, commit=False):
    cursor.close()
    if commit:
        connection.commit()
    connection.close()


def get_cookies(cursor, host_keys=HOST_KEYS):
    query_tmpl = "SELECT host_key, name, value, expires_utc, encrypted_value FROM cookies WHERE host_key IN {:}"
    cursor.execute(query_tmpl.format(host_keys))
    result = cursor.fetchall()
    cookies = decrypt_cookies(result)
    return cookies


def format_long_text(text, max_len=50):
    length = len(text)
    if length <= max_len:
        format_string = "({:d})[{:s}]"
    else:
        format_string =  "({:d})[{:s}...]"
    return format_string.format(length, text[:max_len])


def print_cookie(idx, cookie_tuple, print_data=False):
    print("\nIdx: {:d}\nHost key: {:s}\nName: {:s}\nExpires: {:d}".format(idx, *(cookie_tuple[:3])))
    if print_data:
         print("Decrypted: {:s}".format(format_long_text(cookie_tuple[3])))
         print("Decrypted description: {:s}".format(format_long_text(cookie_tuple[4])))
         print("Data: {:s}".format(format_long_text(cookie_tuple[5])))


def update_cookie(cursor, cookie_tuple):
    decrypted_length = len(cookie_tuple[3])
    encrypted = win32crypt.CryptProtectData(cookie_tuple[3][:decrypted_length // 2], cookie_tuple[4], None, None, None, 0)
    cursor.execute("UPDATE cookies SET encrypted_value = ? WHERE host_key = ? AND name = ?", (buffer(encrypted), cookie_tuple[0], cookie_tuple[1]))


def main():
    conn, cursor = init_db()
    cookies = get_cookies(cursor)
    cookie_idx = 8 % len(cookies) # For simplicity's sake choose an index that references a cookie with an unique `host_key` and `name`
    for idx, cookie_tuple in enumerate(cookies):
        print_cookie(idx, cookie_tuple)
    updated_cookie = cookies[cookie_idx]
    print_cookie(cookie_idx, updated_cookie, print_data=True)
    update_cookie(cursor, updated_cookie)
    shutdown_db(cursor, conn, commit=True)

    print("\nReopening DB...\n")

    conn, cursor = init_db()
    cookies = get_cookies(cursor)
    print("Cookies: {:d}".format(len(cookies)))
    #for idx, cookie_tuple in enumerate(cookies):
    #    print_cookie(idx, cookie_tuple)
    updated_cookie = cookies[cookie_idx]
    print_cookie(cookie_idx, updated_cookie, print_data=True)
    shutdown_db(cursor, conn)


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Notes:

  • I split the code in functions to be more modular (reusable and parameterized)
  • I don't have cookielib installed, so I removed all the parts that reference it, and using tuples to store cookies data instead (I know that dict or collections.namedtuple would have been nicer, but I didn't want to add more code, as this part won't be kept anyway)
  • No error handling
  • Some of the functions are for printing purposes only
  • As a test, I chose one of the cookies and I only keep the 1st half of its (encrypted) data. It will become invalid of course, but it's just for demo purposes only
  • The key is buffer(encrypted) (in update_cookie), since the cookies.encrypted_value column is a BLOB
  • It's Python2 compatible only (noticed #print "Adding cookie" in the question), because in Python3 strings are unicode (and buffer is not present)

Output:

(py27x64_test) e:\Work\Dev\StackOverflow\q050886719>"e:\Work\Dev\VEnvs\py27x64_test\Scripts\python.exe" code.py
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)] on win32


Idx: 0
Host key: .google.com
Name: 1P_JAR
Expires: 13176376602000000

Idx: 1
Host key: .google.com
Name: AID
Expires: 13194604800101431

Idx: 2
Host key: .google.com
Name: APISID
Expires: 13236602265411651

Idx: 3
Host key: .google.com
Name: CGIC
Expires: 13189118241681530

Idx: 4
Host key: .google.com
Name: CGIC
Expires: 13189118241681619

Idx: 5
Host key: .google.com
Name: CONSENT
Expires: 13791196798240053

Idx: 6
Host key: .google.com
Name: GMAIL_RTT
Expires: 0

Idx: 7
Host key: .google.com
Name: HSID
Expires: 13236602265411610

Idx: 8
Host key: .google.com
Name: NID
Expires: 13189336603638418

Idx: 9
Host key: .google.com
Name: SAPISID
Expires: 13236602265411673

Idx: 10
Host key: .google.com
Name: SID
Expires: 13236602265411550

Idx: 11
Host key: .google.com
Name: SIDCC
Expires: 13181563951325551

Idx: 12
Host key: .google.com
Name: SNID
Expires: 13189336552795314

Idx: 13
Host key: .google.com
Name: SSID
Expires: 13236602265411631

Idx: 14
Host key: .google.com
Name: TAID
Expires: 13174995823101361

Idx: 15
Host key: www.google.com
Name: GAPS
Expires: 13229834000111924

Idx: 8
Host key: .google.com
Name: NID
Expires: 13189336603638418
Decrypted: (254)[132=tqLTXZ4dOSPbstdv6oktg9VxbNX3LpwLKGpXzpMwnyVTis...]
Decrypted description: (0)[]
Data: (0)[]

Reopening DB...

Cookies: 16

Idx: 8
Host key: .google.com
Name: NID
Expires: 13189336603638418
Decrypted: (127)[132=tqLTXZ4dOSPbstdv6oktg9VxbNX3LpwLKGpXzpMwnyVTis...]
Decrypted description: (0)[]
Data: (0)[]

Upvotes: 1

Related Questions