Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chromium v53 (v11 cookies and libsecret backend on Ubuntu) #12

Closed
oltodosel opened this issue Sep 6, 2016 · 29 comments
Closed

Chromium v53 (v11 cookies and libsecret backend on Ubuntu) #12

oltodosel opened this issue Sep 6, 2016 · 29 comments
Assignees

Comments

@oltodosel
Copy link

The latest version of chromium has new cookies that start with 'v11' and wouldn't decrypt.

@n8henrie
Copy link
Owner

n8henrie commented Sep 6, 2016

Please provide your operating system and version info.

@oltodosel
Copy link
Author

Linux 4.7.2-1 x86_64
Chromium 52.0.2743.85-20 - has encrypted cookies with v10 at the beginning and it works fine.
Chromium 53.0.2785.92-1 - has encrypted cookies with v11 at the beginning and decryption doesn't work.

@n8henrie
Copy link
Owner

n8henrie commented Sep 6, 2016

Looks like linux still uses the same implementation (v10 / saltysalt / peanuts) unless you're using a third party password-based system.

Still the old version:

Comments on new version with option for v11:

I don't know much about libsecret, I'll have to see if I can figure out how to retrieve the new password for these systems.

@djtm
Copy link

djtm commented Nov 22, 2016

I've noticed that for some values, the encrypted key does not start with either v10 or v11. Examples include __ar_v4 from .hub.docker.com/, ref from www.intel.com/. But it's still encrypted in some way...

@n8henrie
Copy link
Owner

@djtm Hmm, I am only seeing v10 for Docker.com currently. Do you think this is related to this issue?

@djtm
Copy link

djtm commented Nov 26, 2016

I'm not 100% certain it's the same issue. I'll do more testing in the future, next week if all goes well. :)

@stuglaser
Copy link

I am also seeing cookies with a v11 prefix.

Here is an example (from running select * ... in sqlite): v11�I�̫P3ζ�VnG@��[u�}�Ҵ����X-�vfw�kOt"p|��uw6;

Here is the same example base64 encoded: djEx+EmEzKtQM862HVZuR0C3+1t1r33b0rSv6KAWWC0UdmZ3o2tPPwh0InB87dR1dzY7

I am running Google chrome 54.0.2840.71 on Linux (ubuntu)

@n8henrie
Copy link
Owner

Huh, still working for me on OS X, all v10 cookies, and my Linux box broke. Reinstalling Arch, will be able to test soon. Would appreciate help from anyone knowledgeable about libsecret as mentioned above -- hopefully it may be as simple as getting the Chrome pw from keychain on OSX.

@djtm
Copy link

djtm commented Dec 3, 2016

I think starting Chrome with --password-store=basic might be a workaround.

@n8henrie n8henrie self-assigned this Dec 11, 2016
@djtm
Copy link

djtm commented Jan 3, 2017

It looks like it's implemented here: https://github.com/bertrandom/chrome-cookies-secure/blob/master/index.js

I'm guessing /usr/bin/google-chrome --use-mock-keychain might also be the right way to avoid the issue.

@ghost
Copy link

ghost commented Feb 15, 2017

Affecting me too.. I've been trying to get the passwords out of keyring with no luck. --password-store=basic and --use-mock-keychain didn't work for me

@ghost
Copy link

ghost commented Feb 16, 2017

Okay so I managed to extract the passwords from libsecret, they are in a service called "Chrome Safe Storage"

import gi
gi.require_version('Secret', '1')
from gi.repository import Secret

def get_cookie_password():
    service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)

    default_keyring = service.get_collections()[0]
    default_keyring = service.unlock_sync([default_keyring])[1][0]

    for item in (default_keyring.get_items()):
        if item.get_label() == "Chrome Safe Storage":
            item.load_secret_sync()
            return item.get_secret().get_text()

    return None

Hit me up if that doesn't work for you

You can also use the command line:

$ secret-tool search application chrome

@n8henrie
Copy link
Owner

Sweet, thanks. I tried and couldn't replicate the issue a couple days ago, but I forgot to check what version of Chromium I was running (couldn't be too old, a fresh Arch installation from scratch within the last month or two). When I get back to my Arch box I'll see if I can figure out how to reproduce, and if so how to incorporate this.

Thanks again for the updates.

@djtm
Copy link

djtm commented Feb 20, 2017

@trideceth12: Could you send a pull request? Makes it easier to try this out. I'd be happy to try it.

$ secret-tool search application chromium works for me. Chrome didn't.

@n8henrie
Copy link
Owner

n8henrie commented Mar 7, 2017

I can't replicate the issue on Chromium 56.0.2924.87-1 on Arch Linux, cookies still have v10 prefix, all tests pass. I wonder why we're seeing a difference here.

@djtm
Copy link

djtm commented Mar 7, 2017

Which desktop environment do you use @n8henrie ? Depending on your environment, chrome might not find a keychain to store it's encryption key in. I think you get this in recent Ubuntu and Kubuntu.

@n8henrie
Copy link
Owner

n8henrie commented Mar 7, 2017

That could be it. I'm on wayland / sway.

@stat1c1c3au
Copy link

stat1c1c3au commented Apr 2, 2017

Hi! I'm new to GitHub and Python so please be nice :)

I couldn't check in a Branch to create a Pull Request so here's what I did to make it work.

  1. Install additional Python libraries
    sudo apt-get install libsecret-1-dev
    sudo apt-get install python-gi

  2. Merging the code from @trideceth12 into pycookiecheat.py

added after import sys:
import platform

added before def chrome_cookies

# used for reading from keychain
if sys.platform == "linux2" and "Ubuntu" in platform.platform():
    try:
        import gi
        gi.require_version('Secret', '1')
        from gi.repository import Secret
    except ImportError:
        raise Exception("Error: please install libsecret-1-dev and/or python-gi using apt-get")

def get_cookie_password():
    service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)

    default_keyring = service.get_collections()[0]
    default_keyring = service.unlock_sync([default_keyring])[1][0]

    for item in (default_keyring.get_items()):
        if item.get_label() == "Chrome Safe Storage":
            item.load_secret_sync()
            return item.get_secret().get_text()

    return None

added after my_pass = 'peanuts'.encode('utf8')
my_pass_v11 = get_cookie_password()

added after kdf = PBKDF2HMAC...

    kdf_v11 = PBKDF2HMAC(
        algorithm=SHA1(),
        length=length,
        salt=salt,
        iterations=iterations,
        backend=default_backend(),
    )
    key_v11 = kdf_v11.derive(bytes(my_pass_v11))

changed last decryption block to:

        for k, v, ev in conn.execute(sql, (host_key,)):
            # if there is a not encrypted value or if the encrypted value
            # doesn't start with the 'v10'/'v11' prefix, return v
            if v or (ev[:3] != b'v10' and ev[:3] != b'v11'):
                cookies_list.append((k, v))
            elif (ev[:3] == b'v11'):
                decrypted_tuple = (k, chrome_decrypt(ev, key=key_v11))
                cookies_list.append(decrypted_tuple)
            else:
                decrypted_tuple = (k, chrome_decrypt(ev, key=key))
                cookies_list.append(decrypted_tuple)

Just needs more testing to better handle exceptions and other platforms.

@n8henrie - Issue occurred on Ubuntu 16.04.2 Desktop 64 bit with Google Chrome 57.0.2987.133 installed from Google.

Let me know if you need more information!

@n8henrie
Copy link
Owner

n8henrie commented Apr 4, 2017

Great, thanks for getting me the version numbers. I'll see if I can spin up a VM and reproduce, if so will try to merge in that code.

@borisbabic
Copy link

It would probably be better to check the desktop environment since that is the default for --password-store:


       --password-store=<basic|gnome|kwallet>
              Set the password store to use.  The default is to automatically detect based on the desktop environment.  basic selects the built in, unencrypted password store.  gnome selects Gnome keyring.   kwallet  selects  (KDE)

@n8henrie
Copy link
Owner

n8henrie commented Apr 6, 2017

Many thanks to @stat1c1c3au @trideceth12 -- been plugging away on Virtualbox / Ubuntu all day and have incorporated your code in a way that seems to work without breaking anything.

https://github.com/n8henrie/pycookiecheat/tree/56ccaf345e1dcf74ff0db1af2dbd9a5eebb43721

NB: If using in a virtualenv, you apparently have to use the --system-site-packages flag in order to get access to the necessary gi libraries, no way to install them directly.

@n8henrie
Copy link
Owner

Don't know if anybody has had time to test, but I'm going to go ahead and merge into master. I would really like to get better automated testing ideally using something like Selenium (especially since I'm not primarily on Linux, and when I am it's Arch, which is part of the reason I had such a hard time replicating this issue). I've started a docker-selenium branch to see if that might be a good solution, but I've never used either of these technologies, so would be happy to have help if anyone has more experience here. Specifically, would be nice to have CI testing on a Ubuntu 16.04 distro that uses the commits from this thread.

@stat1c1c3au
Copy link

stat1c1c3au commented Apr 17, 2017

Hey @n8henrie. Sorry, only just had a chance to try this out and have a couple of issues:

1/ Ubuntu

It seems that it's not quite pulling the password out of the keyring. my_pass is still being set to 'peanuts'

Debugging, I tracked it down to this code:

            gnome_keyring = service.get_collections()
            unlocked_keyring = service.unlock_sync(gnome_keyring).unlocked[0]

and had to change it to this to make it work:

            gnome_keyring = service.get_collections()[0]
            unlocked_keyring = service.unlock_sync([gnome_keyring]).unlocked[0]

2/ macOS Sierra 10.12.3

I couldn't upgrade using sudo pip install --upgrade pycookiecheat
Had to do this: sudo pip install --ignore-installed six --upgrade pycookiecheat

Ran into an issue when pip tried to uninstall the "six" package:

Installing collected packages: six, pyparsing, packaging, asn1crypto, appdirs, setuptools, cryptography, keyring, pycookiecheat
  Found existing installation: six 1.4.1
    DEPRECATION: Uninstalling a distutils installed project (six) has been deprecated and will be removed in a future version. This is due to the fact that uninstalling a distutils project will only partially uninstall the project.
    Uninstalling six-1.4.1:
Exception:
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/commands/install.py", line 342, in run
    prefix=options.prefix_path,
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/req/req_set.py", line 778, in install
    requirement.uninstall(auto_confirm=True)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/req/req_install.py", line 754, in uninstall
    paths_to_remove.remove(auto_confirm)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/req/req_uninstall.py", line 115, in remove
    renames(path, new_path)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/utils/__init__.py", line 267, in renames
    shutil.move(old, new)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 302, in move
    copy2(src, real_dst)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 131, in copy2
    copystat(src, dst)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 103, in copystat
    os.chflags(dst, st.st_flags)
OSError: [Errno 1] Operation not permitted: '/tmp/pip-QRL7Xx-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six-1.4.1-py2.7.egg-info'

Is this normal?

Thanks!

@n8henrie n8henrie changed the title Chromium v53 Chromium v53 (v11 cookies and libsecretbackend on Ubuntu) Apr 17, 2017
@n8henrie n8henrie changed the title Chromium v53 (v11 cookies and libsecretbackend on Ubuntu) Chromium v53 (v11 cookies and libsecret backend on Ubuntu) Apr 17, 2017
@n8henrie n8henrie reopened this Apr 17, 2017
@n8henrie
Copy link
Owner

Hmmm...

Debugging, I tracked it down to this code:

gnome_keyring = service.get_collections()
unlocked_keyring = service.unlock_sync(gnome_keyring).unlocked[0]

and had to change it to this to make it work:

gnome_keyring = service.get_collections()[0]
unlocked_keyring = service.unlock_sync([gnome_keyring]).unlocked[0]

Unfortunately, I changed that line because the way it's working for you wasn't working for me. We'll have to track this down.

gnome_keyring = service.get_collections()
unlocked_keyring = service.unlock_sync(gnome_keyring).unlocked[0]

vs

gnome_keyring = service.get_collections()[0]`
unlocked_keyring = service.unlock_sync([gnome_keyring]).unlocked[0]

The way I have it, service.get_collections() returns a list of all collections. I assumed the reason that service.get_collections()[0] wasn't working for me is that it only returns the first collection, and perhaps my setup was using a different one and should therefore return all collections.

That said, the service.unlock_sync(gnome_keyring).unlocked[0] will only return the first unlocked one, so it probably doesn't matter if I return all or just one. I'll mess around with this a little more today.

2/ macOS Sierra 10.12.3

I couldn't upgrade using sudo pip install --upgrade pycookiecheat
Had to do this: sudo pip install --ignore-installed six --upgrade pycookiecheat

I'd really rather you not install into the system site-packages. Please use a virtualenv.

I think to find the source of the error you'd have to go through the dependencies and find which one / where they were trying to upgrade six -- I think this may be an upstream issue from one of the dependencies. The quick answer is that you should generally be using virtualenvs, especially for debugging or development purposes, and that should fix this issue.

@n8henrie
Copy link
Owner

@stat1c1c3au Please test my latest dev commit: c55c9c7

$ pip install git+https://github.com/n8henrie/pycookiecheat@c55c9c77652fe2fa5f498f11b98cc80dcf36bdfa#egg=pycookiecheat

@stat1c1c3au
Copy link

@n8henrie latest dev commit is good 👍

and thanks for the tip on the virtualenv

@n8henrie
Copy link
Owner

n8henrie commented Apr 19, 2017 via email

@n8henrie
Copy link
Owner

v0.3.5 is out on PyPI. Thanks for helping sort this out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants