-
Notifications
You must be signed in to change notification settings - Fork 792
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
3426 linux chrome credentials collector #3665
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we copied this from somewhere, make sure we include the original author, source repository link, and license information at the top.
monkey/agent_plugins/credentials_collectors/chrome/src/linux_credentials_database_selector.py
Outdated
Show resolved
Hide resolved
monkey/agent_plugins/credentials_collectors/chrome/src/linux_credentials_database_selector.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, this PR is too big. Rebase and then split into smaller PRs. Suggestion: 1 for collector and one for processor.
b195cdc
to
f978052
Compare
1f6c3e3
to
238959f
Compare
a817ceb
to
d6555c1
Compare
17da9d8
to
eb80534
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure you test manually
("Brave", ".config/BraveSoftware/Brave-Browser"), | ||
("SlimJet", ".config/slimjet"), | ||
("Dissenter Browser", ".config/GabAI/Dissenter-Browser"), | ||
("Vivaldi", ".config/vivaldi"), | ||
("Microsoft Edge (Dev)", ".config/microsoft-edge-dev"), | ||
("Microsoft Edge (Beta)", ".config/microsoft-edge-beta"), | ||
("Microsoft Edge", ".config/microsoft-edge"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove all of these. We're only supporting Chrome and Chromium on Linux.
monkey/agent_plugins/credentials_collectors/chrome/src/linux_credentials_database_selector.py
Show resolved
Hide resolved
monkey/agent_plugins/credentials_collectors/chrome/src/linux_credentials_database_selector.py
Show resolved
Hide resolved
for browser_name, browser_path in CHROMIUM_BASED_DB_PATHS: | ||
browser_db_path = home_dir_path / browser_path | ||
try: | ||
if self._directory_is_accessible(browser_db_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be the processor's responsibility
try: | ||
sub_profile_dirs = profile_dir_path.iterdir() | ||
for subdir in sub_profile_dirs: | ||
if subdir == (profile_dir_path / LOGIN_DATABASE_FILENAME): | ||
if self._file_is_accessible(subdir): | ||
login_data_paths.add( | ||
BrowserCredentialsDatabasePath( | ||
database_file_path=subdir, master_key=DEFAULT_MASTER_KEY | ||
) | ||
) | ||
|
||
login_database_path = profile_dir_path / subdir / LOGIN_DATABASE_FILENAME | ||
if self._file_is_accessible(login_database_path): | ||
login_data_paths.add( | ||
BrowserCredentialsDatabasePath( | ||
database_file_path=login_database_path, master_key=DEFAULT_MASTER_KEY | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flake8 doesn't complain about complexity here?
) | ||
|
||
login_database_path = profile_dir_path / subdir / LOGIN_DATABASE_FILENAME | ||
if self._file_is_accessible(login_database_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be the processor's responsibility
sub_profile_dirs = profile_dir_path.iterdir() | ||
for subdir in sub_profile_dirs: | ||
if subdir == (profile_dir_path / LOGIN_DATABASE_FILENAME): | ||
if self._file_is_accessible(subdir): | ||
login_data_paths.add( | ||
BrowserCredentialsDatabasePath( | ||
database_file_path=subdir, master_key=DEFAULT_MASTER_KEY | ||
) | ||
) | ||
|
||
login_database_path = profile_dir_path / subdir / LOGIN_DATABASE_FILENAME | ||
if self._file_is_accessible(login_database_path): | ||
login_data_paths.add( | ||
BrowserCredentialsDatabasePath( | ||
database_file_path=login_database_path, master_key=DEFAULT_MASTER_KEY | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems way more complex than it needs to be.
Just do:
sub_profile_dirs = profile_dir_path.iterdir()
if (profile_dir_path / LOGIN_DATABASE_FILENAME).exists():
login_data_paths.add(...)
for subdir in sub_profile_dirs:
login_database_path = profile_dir_path / subdir / LOGIN_DATABASE_FILENAME
login_data_paths.add(...)
def __call__(self) -> Collection[BrowserCredentialsDatabasePath]: | ||
return [] | ||
database_paths: Set[BrowserCredentialsDatabasePath] = set() | ||
for profile_dir in self._get_browser_database_paths(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The paths being returned from self._get_browser_database_paths()
are not profile directory paths. They're browser directory paths for each user on the system. The name profile_dir
makes it seem like you're talking about the profiles in the browser.
) | ||
) | ||
|
||
login_database_path = profile_dir_path / subdir / LOGIN_DATABASE_FILENAME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are all the files inside profile_dir_path
only for the browser's user profiles? If no, this could add files to login_data_paths
that aren't related to user profiles in any way.
Can't you just check the name of the directories and then add them to the set like we do for Windows? In Windows, we check for directories that start with "Profile".
d6555c1
to
87662ba
Compare
e25e9c8
to
12d09c3
Compare
87662ba
to
9f745a6
Compare
92694a6
to
b3e8df5
Compare
if home_path not in home_dirs.values(): | ||
home_dirs[os.getlogin()] = home_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this check necessary?
if "HOME" in os.environ: | ||
home_path = Path(os.environ["HOME"]) | ||
if home_path not in home_dirs.values(): | ||
home_dirs[os.getlogin()] = home_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is any of this necessary?
if (browser_database_path / LOGIN_DATABASE_FILENAME).exists(): | ||
login_data_paths.add( | ||
BrowserCredentialsDatabasePath( | ||
database_file_path=(browser_database_path / LOGIN_DATABASE_FILENAME), | ||
master_key=DEFAULT_MASTER_KEY, | ||
) | ||
) | ||
|
||
sub_browser_database_paths = browser_database_path.iterdir() | ||
for subdir in sub_browser_database_paths: | ||
login_database_path = browser_database_path / subdir / LOGIN_DATABASE_FILENAME | ||
if login_database_path.exists(): | ||
login_data_paths.add( | ||
BrowserCredentialsDatabasePath( | ||
database_file_path=login_database_path, master_key=DEFAULT_MASTER_KEY | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all of these conditions and all of the searching can just be replaced with a glob.
for database_file in browser_database_path.glob(f'**/{LOGIN_DATABASE_FILENAME}'):
login_data_paths.add(...)
^ Not tested.
monkey/agent_plugins/credentials_collectors/chrome/src/linux_credentials_database_selector.py
Show resolved
Hide resolved
home_dirs = { | ||
p.pw_name: Path(p.pw_dir) for p in pwd.getpwall() # type: ignore[attr-defined] | ||
} | ||
|
||
return home_dirs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
home_dirs = { | |
p.pw_name: Path(p.pw_dir) for p in pwd.getpwall() # type: ignore[attr-defined] | |
} | |
return home_dirs | |
return { | |
p.pw_name: Path(p.pw_dir) for p in pwd.getpwall() # type: ignore[attr-defined] | |
} |
try: | ||
if browser_db_path.exists(): | ||
database_paths.append(browser_db_path) | ||
except Exception as err: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exception can be raised here?
06512dd
to
d48dd12
Compare
try: | ||
login_data_paths = self._get_login_data_paths(browser_database_path) | ||
database_paths.update(login_data_paths) | ||
except Exception: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exception can be raised here? Would it be better handled within _get_login_data_paths()
so that function doesn't short circuit?
if browser_db_path.exists(): | ||
database_paths.append(browser_db_path) | ||
except Exception as err: | ||
logger.exception( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logs at the error level. Does the average user really need an error message?
We only want Chrome and Chromium
8f64dd5
to
7661839
Compare
7661839
to
3d5f087
Compare
What does this PR do?
Fixes #
put issue number here
.Add any further explanations here.
PR Checklist
Testing Checklist