-
Notifications
You must be signed in to change notification settings - Fork 144
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
Firefox cookies from given container in Multi-Account Containers #205
Comments
I have solved this myself for my usecase. |
Hi @rez-spb! Can you share your solution for extracting cookies from Firefox containers? I haven't been able to find a way to do so myself as yet! Thank you so much! |
I also have the same issue |
This extension of the class FirefoxUserSpecific(browser_cookie3.Firefox):
def __init__(self, domain_name: str, user_context_id: int):
self.user_context_id = user_context_id
super().__init__(domain_name=domain_name)
# Monkey patch the FirefoxBased.load method to customize cookie loading
def load(self, *args, **kwargs):
import http.cookiejar
cj = http.cookiejar.CookieJar()
# firefoxbased seems faster with legacy mode
with browser_cookie3._DatabaseConnetion(self.cookie_file, True) as con:
cur = con.cursor()
cur.execute('select host, path, isSecure, expiry, name, value, isHttpOnly from moz_cookies '
f'where host like ? and originAttributes like "%^userContextID={self.user_context_id}%"', ('%{}%'.format(self.domain_name),))
all = cur.fetchall();
for item in all:
host, path, secure, expires, name, value, http_only = item
c = browser_cookie3.create_cookie(host, path, secure, expires,
name, value, http_only)
cj.set_cookie(c)
# the relevant file doesn't exist in my testing - may need to support this
# getattr(self, '_FirefoxBased__add_session_cookies')(cj)
self.add_session_cookies_lz4(cj)
return cj
def add_session_cookies_lz4(self, cj):
import lz4.block
if not os.path.exists(self.session_file_lz4):
return
try:
with open(self.session_file_lz4, 'rb') as file_obj:
file_obj.read(8)
json_data = json.loads(lz4.block.decompress(file_obj.read()))
except ValueError as e:
print(
f'Error parsing {self.browser_name} session JSON LZ4:', str(e))
else:
for cookie in json_data.get('cookies', []):
if self.domain_name == '' or self.domain_name in cookie.get('host', ''):
if cookie['originAttributes']['userContextId'] == self.user_context_id:
cj.set_cookie(getattr(self, '_FirefoxBased__create_session_cookie')(cookie)) |
@Vetches, sorry I have missed the reply in July. My bad. class FirefoxBased(browser_cookie3.FirefoxBased):
def __init__(self, browser_name, cookie_file=None, domain_name="", container_id=None, **kwargs):
super().__init__(browser_name, cookie_file, domain_name, **kwargs)
self.container_id = container_id
def load(self):
cj = http.cookiejar.CookieJar()
with browser_cookie3._DatabaseConnetion(self.cookie_file, True) as con:
cur = con.cursor()
container_id = self.container_id
if container_id:
cur.execute('select host, path, isSecure, expiry, name, value, isHttpOnly, originAttributes from moz_cookies '
'where host like ? and originAttributes like ?', ('%{}%'.format(self.domain_name),
'^userContextId={}&%'.format(container_id)))
for item in cur.fetchall():
host, path, secure, expires, name, value, http_only, origin = item
c = browser_cookie3.create_cookie(host, path, secure, expires, name, value, http_only)
cj.set_cookie(c)
else:
cur.execute(
'select host, path, isSecure, expiry, name, value, isHttpOnly from moz_cookies '
'where host like ?', ('%{}%'.format(self.domain_name),))
for item in cur.fetchall():
host, path, secure, expires, name, value, http_only = item
c = browser_cookie3.create_cookie(host, path, secure, expires, name, value, http_only)
cj.set_cookie(c)
self.__add_session_cookies(cj)
self.__add_session_cookies_lz4(cj)
return cj
class Firefox(FirefoxBased):
"""Class for Firefox"""
def __init__(self, cookie_file=None, domain_name="", container_id=None):
args = {
'linux_data_dirs': [
'~/snap/firefox/common/.mozilla/firefox',
'~/.mozilla/firefox'
],
'windows_data_dirs': [
{'env': 'APPDATA', 'path': r'Mozilla\Firefox'},
{'env': 'LOCALAPPDATA', 'path': r'Mozilla\Firefox'}
],
'osx_data_dirs': [
'~/Library/Application Support/Firefox'
]
}
super().__init__('Firefox', cookie_file, domain_name, container_id, **args) Used in internal projects this way: cj = Firefox(domain_name='example.com', container_id=666).load() |
Thank you both so, so much for taking the time to reply, this is incredibly helpful!! |
How does this module handle Multi-Account Containers in Firefox?
From what I've read (http://justsolve.archiveteam.org/wiki/Firefox_cookie_database), FF introduced
originAttributes
column since August, 2022, which I see present in SQLite DB.Example value for this DB column:
^userContextId=1&firstPartyDomain=somedomain.com
I have several containers with different
userContextId
used for one site/host but with different credentials and cookies.Is it possible for this module to address only cookies in particular container?
Currently it looks like it takes arbitrary one and my cookies are a mess: some fields are taken from one container, others may be from another, and it seems that there's no way to separate them due to internal
CookieJar
object having nooriginAttributes
field (searched in code for this, didn't find it).Usecase:
Actual result:
Get one
CookieJar
object with randomly selected container and fields.Expected result:
Get 3 objects with IDs for each container (including default) totally separated from one another with proper cookies for each.
Ability to select from returned objects by ID would also be much appreciated.
Hope I didn't miss something, because there's little documentation so I had to to try and err on this one.
The text was updated successfully, but these errors were encountered: