Instantly share code, notes, and snippets.
-
Star
0
(0)
You must be signed in to star a gist -
Fork
1
(1)
You must be signed in to fork a gist
-
-
Save cyrozap/74410b5d81d1b2c9c6f0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| '''pyCookieCheat.py | |
| 20140701 v 2.1: Modularized the code, made it compatible with Python 2, and added an encryption function | |
| Use your browser's cookies to make grabbing data from login-protected sites easier. | |
| Intended for use with Python Requests http://python-requests.org | |
| Accepts a URL from which it tries to extract a domain. If you want to force the domain, | |
| just send it the domain you'd like to use instead. | |
| Intended use with requests: | |
| import requests | |
| import pyCookieCheat | |
| url = 'http://www.example.com' | |
| s = requests.Session() | |
| cookies = pyCookieCheat.chrome_cookies(url) | |
| s.get(url, cookies = cookies) | |
| Adapted from n8henrie's code at http://n8h.me/HufI1w | |
| Helpful Links: | |
| * Chromium Mac os_crypt: http://n8h.me/QWRgK8 | |
| * Chromium Linux os_crypt: http://n8h.me/QWTglz | |
| * Python Crypto: http://n8h.me/QWTqte | |
| ''' | |
| import os.path | |
| import sqlite3 | |
| import sys | |
| import urlparse | |
| import keyring | |
| from Crypto.Cipher import AES | |
| from Crypto.Protocol.KDF import PBKDF2 | |
| def generate_key(my_pass, iterations): | |
| """Generate an encryption key from the specified password and number of iterations""" | |
| salt = 'saltysalt' | |
| length = 16 | |
| return PBKDF2(my_pass, salt, length, iterations) | |
| def get_parameters(): | |
| """Get OS-specific parameters""" | |
| # If running Chrome on OSX | |
| if sys.platform == 'darwin': | |
| my_pass = keyring.get_password('Chrome Safe Storage', 'Chrome') | |
| my_pass = my_pass.encode('utf8') | |
| iterations = 1003 | |
| cookie_file = os.path.expanduser( | |
| '~/Library/Application Support/Google/Chrome/Default/Cookies' | |
| ) | |
| # If running Chromium on Linux | |
| elif sys.platform == 'linux': | |
| my_pass = 'peanuts'.encode('utf8') | |
| iterations = 1 | |
| cookie_file = os.path.expanduser( | |
| '~/.config/chromium/Default/Cookies' | |
| ) | |
| else: | |
| raise Exception("This script only works on OSX or Linux.") | |
| return (my_pass, iterations, cookie_file) | |
| def chrome_decrypt(encrypted_value, key=None): | |
| """Decrypt the plaintext cookie with key""" | |
| # Encrypted cookies should be prefixed with 'v10' according to the | |
| # Chromium code. Strip it off. | |
| encrypted_value = encrypted_value[3:] | |
| # Strip padding by taking off number indicated by padding | |
| # eg if last is '\x0e' then ord('\x0e') == 14, so take off 14. | |
| def clean(x): | |
| return x[:-ord(x[-1])].decode('utf8') | |
| cipher = AES.new(key, AES.MODE_CBC, IV = ' ' * 16) | |
| decrypted = cipher.decrypt(encrypted_value) | |
| return clean(decrypted) | |
| def chrome_encrypt(plaintext, key=None): | |
| """Encrypt the plaintext cookie with key""" | |
| # Add padding to ensure a 16-byte blocksize | |
| def pad(x): | |
| pad_length = 16 - (len(x) % 16) | |
| if pad_length != 0: | |
| padding = chr(pad_length) * pad_length | |
| else: | |
| padding = '' | |
| return '%s%s' % (x, padding) | |
| cipher = AES.new(key, AES.MODE_CBC, IV = ' ' * 16) | |
| encrypted = cipher.encrypt(pad(plaintext)) | |
| # Encrypted cookies should be prefixed with 'v10' according to the | |
| # Chromium code. Add it. | |
| encrypted = 'v10%s' % encrypted | |
| return encrypted | |
| def chrome_cookies(url): | |
| """Get cookies for the specified URL""" | |
| (my_pass, iterations, cookie_file) = get_parameters() | |
| key = generate_key(my_pass, iterations) | |
| # Part of the domain name that will help the sqlite3 query pick it from the Chrome cookies | |
| domain = urlparse.urlparse(url).netloc | |
| conn = sqlite3.connect(cookie_file) | |
| sql = 'SELECT name, value, encrypted_value FROM cookies '\ | |
| 'WHERE host_key LIKE "%{}%"'.format(domain) | |
| cookies = {} | |
| cookies_list = [] | |
| with conn: | |
| for k, v, ev in conn.execute(sql): | |
| # if there is a not encrypted value or if the encrypted value | |
| # doesn't start with the 'v10' prefix, return v | |
| if v or (ev[:3] != b'v10'): | |
| cookies_list.append((k, v)) | |
| else: | |
| decrypted_tuple = (k, chrome_decrypt(ev, key=key)) | |
| cookies_list.append(decrypted_tuple) | |
| cookies.update(cookies_list) | |
| return cookies |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment