Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3aeeb1d
add browser.passwords function
JSCU-CNI Feb 16, 2024
22232f5
fix linter
JSCU-CNI Feb 16, 2024
a5cfcab
add brave.passwords
JSCU-CNI Feb 16, 2024
c265251
move browser helper funcs to main plugin files
JSCU-CNI Feb 29, 2024
786b673
implement review comments
JSCU-CNI Feb 29, 2024
21dea84
implement keychain support
JSCU-CNI Mar 1, 2024
cdb7f1e
add dpapi test for chrome
JSCU-CNI Mar 1, 2024
5555ae1
change log messages
JSCU-CNI Mar 1, 2024
3b24a67
implement review comments
JSCU-CNI Mar 4, 2024
3ade668
revert changes to registry tool
JSCU-CNI Mar 4, 2024
24576e9
decrypt chromium cookie values
JSCU-CNI Mar 6, 2024
e3361b9
Apply suggestions from code review
JSCU-CNI Mar 18, 2024
8d800ac
implement review comments
JSCU-CNI Mar 18, 2024
4d2b723
fix crypto imports across dissect
JSCU-CNI Mar 18, 2024
c3c7919
implement review comments
JSCU-CNI Mar 20, 2024
f307e6f
Apply suggestions from code review
JSCU-CNI Mar 20, 2024
509dbbc
Small change suggestions
Schamper Apr 9, 2024
b782e52
Update dissect/target/plugins/os/windows/dpapi/dpapi.py
Schamper Apr 10, 2024
42fe5b5
Update dissect/target/plugins/os/windows/dpapi/dpapi.py
Schamper Apr 10, 2024
fa2b7f8
Revert "revert changes to registry tool"
Schamper Apr 10, 2024
974deda
Apply suggestions from code review
JSCU-CNI Apr 15, 2024
fae32d9
implement review comments
JSCU-CNI Apr 15, 2024
6adc976
Merge branch 'main' into feature/add-browser-password-funcs
JSCU-CNI Apr 15, 2024
adfcd07
Merge branch 'main' into feature/add-browser-password-funcs
JSCU-CNI Apr 16, 2024
b88a6e3
Merge branch 'main' into feature/add-browser-password-funcs
Schamper Apr 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions dissect/target/loaders/itunes.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
try:
from Crypto.Cipher import AES

HAS_PYCRYPTODOME = True
HAS_CRYPTO = True
except ImportError:
HAS_PYCRYPTODOME = False
HAS_CRYPTO = False


DOMAIN_TRANSLATION = {
Expand Down Expand Up @@ -383,7 +383,7 @@ def _create_cipher(key: bytes, iv: bytes = b"\x00" * 16, mode: str = "cbc") -> A
raise ValueError(f"Invalid key size: {key_size}")

return _pystandalone.cipher(f"aes-{key_size * 8}-{mode}", key, iv)
elif HAS_PYCRYPTODOME:
elif HAS_CRYPTO:
mode_map = {
"cbc": (AES.MODE_CBC, True),
"ecb": (AES.MODE_ECB, False),
Expand Down
10 changes: 10 additions & 0 deletions dissect/target/plugins/apps/browser/brave.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
GENERIC_DOWNLOAD_RECORD_FIELDS,
GENERIC_EXTENSION_RECORD_FIELDS,
GENERIC_HISTORY_RECORD_FIELDS,
GENERIC_PASSWORD_RECORD_FIELDS,
BrowserPlugin,
)
from dissect.target.plugins.apps.browser.chromium import (
Expand Down Expand Up @@ -47,6 +48,10 @@ class BravePlugin(ChromiumMixin, BrowserPlugin):
"browser/brave/extension", GENERIC_EXTENSION_RECORD_FIELDS
)

BrowserPasswordRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
"browser/brave/password", GENERIC_PASSWORD_RECORD_FIELDS
)

@export(record=BrowserHistoryRecord)
def history(self) -> Iterator[BrowserHistoryRecord]:
"""Return browser history records for Brave."""
Expand All @@ -66,3 +71,8 @@ def downloads(self) -> Iterator[BrowserDownloadRecord]:
def extensions(self) -> Iterator[BrowserExtensionRecord]:
"""Return browser extension records for Brave."""
yield from super().extensions("brave")

@export(record=BrowserPasswordRecord)
def passwords(self) -> Iterator[BrowserPasswordRecord]:
"""Return browser password records for Brave."""
yield from super().passwords("brave")
43 changes: 43 additions & 0 deletions dissect/target/plugins/apps/browser/browser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from functools import cache

from dissect.target.helpers import keychain
from dissect.target.helpers.descriptor_extensions import UserRecordDescriptorExtension
from dissect.target.helpers.record import create_extended_descriptor
from dissect.target.plugin import NamespacePlugin
from dissect.target.target import Target

GENERIC_DOWNLOAD_RECORD_FIELDS = [
("datetime", "ts_start"),
Expand Down Expand Up @@ -63,6 +67,21 @@
("uri", "from_url"),
("path", "source"),
]

GENERIC_PASSWORD_RECORD_FIELDS = [
("datetime", "ts_created"),
("datetime", "ts_last_used"),
("datetime", "ts_last_changed"),
("string", "browser"),
("varint", "id"),
("uri", "url"),
("string", "encrypted_username"),
("string", "encrypted_password"),
("string", "decrypted_username"),
("string", "decrypted_password"),
("path", "source"),
]

BrowserDownloadRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
"browser/download", GENERIC_DOWNLOAD_RECORD_FIELDS
)
Expand All @@ -75,11 +94,35 @@
BrowserCookieRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
"browser/cookie", GENERIC_COOKIE_FIELDS
)
BrowserPasswordRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
"browser/password", GENERIC_PASSWORD_RECORD_FIELDS
)


class BrowserPlugin(NamespacePlugin):
__namespace__ = "browser"

def __init__(self, target: Target):
super().__init__(target)
self.keychain = cache(self.keychain)

def keychain(self) -> set:
"""Retrieve a set of passphrases to use for decrypting saved browser credentials.

Always adds an empty passphrase as some browsers encrypt values using empty passphrases.

Returns:
Set of passphrase strings.
"""
passphrases = set()
for provider in [self.__namespace__, "browser", "user", None]:
for key in keychain.get_keys_for_provider(provider) if provider else keychain.get_keys_without_provider():
if key.key_type == keychain.KeyType.PASSPHRASE:
passphrases.add(key.value)

passphrases.add("")
return passphrases


def try_idna(url: str) -> bytes:
"""Attempts to convert a possible Unicode url to ASCII using the IDNA standard.
Expand Down
10 changes: 10 additions & 0 deletions dissect/target/plugins/apps/browser/chrome.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
GENERIC_DOWNLOAD_RECORD_FIELDS,
GENERIC_EXTENSION_RECORD_FIELDS,
GENERIC_HISTORY_RECORD_FIELDS,
GENERIC_PASSWORD_RECORD_FIELDS,
BrowserPlugin,
)
from dissect.target.plugins.apps.browser.chromium import (
Expand Down Expand Up @@ -49,6 +50,10 @@ class ChromePlugin(ChromiumMixin, BrowserPlugin):
"browser/chrome/extension", GENERIC_EXTENSION_RECORD_FIELDS
)

BrowserPasswordRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
"browser/chrome/password", GENERIC_PASSWORD_RECORD_FIELDS
)

@export(record=BrowserHistoryRecord)
def history(self) -> Iterator[BrowserHistoryRecord]:
"""Return browser history records for Google Chrome."""
Expand All @@ -68,3 +73,8 @@ def downloads(self) -> Iterator[BrowserDownloadRecord]:
def extensions(self) -> Iterator[BrowserExtensionRecord]:
"""Return browser extension records for Google Chrome."""
yield from super().extensions("chrome")

@export(record=BrowserPasswordRecord)
def passwords(self) -> Iterator[BrowserPasswordRecord]:
"""Return browser password records for Google Chrome."""
yield from super().passwords("chrome")
Loading