Skip to content

Commit

Permalink
Merge branch 'main' into py313-support
Browse files Browse the repository at this point in the history
  • Loading branch information
Schamper authored Jan 2, 2025
2 parents 0bb0f3f + 6770095 commit 0389348
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 16 deletions.
8 changes: 6 additions & 2 deletions dissect/target/plugins/os/unix/linux/_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from dissect.target.plugins.os.unix.bsd.osx._os import MacPlugin
from dissect.target.plugins.os.unix.linux.network_managers import (
LinuxNetworkManager,
parse_unix_dhcp_leases,
parse_unix_dhcp_log_messages,
)
from dissect.target.plugins.os.windows._os import WindowsPlugin
Expand Down Expand Up @@ -39,8 +40,11 @@ def ips(self) -> list[str]:
for ip_set in self.network_manager.get_config_value("ips"):
ips.update(ip_set)

for ip in parse_unix_dhcp_log_messages(self.target, iter_all=False):
ips.add(ip)
if dhcp_lease_ips := parse_unix_dhcp_leases(self.target):
ips.update(dhcp_lease_ips)

elif dhcp_log_ips := parse_unix_dhcp_log_messages(self.target, iter_all=False):
ips.update(dhcp_log_ips)

return list(ips)

Expand Down
35 changes: 35 additions & 0 deletions dissect/target/plugins/os/unix/linux/network_managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from defusedxml import ElementTree

from dissect.target.exceptions import PluginError
from dissect.target.helpers import configutil

if TYPE_CHECKING:
from dissect.target.helpers.fsutil import TargetPath
Expand Down Expand Up @@ -601,6 +602,40 @@ def records_enumerate(iterable: Iterable) -> Iterator[tuple[int, JournalRecord |
return ips


def parse_unix_dhcp_leases(target: Target) -> set[str]:
"""Parse NetworkManager and dhclient DHCP ``.lease`` files.
Resources:
- https://linux.die.net/man/5/dhclient.conf
Args:
target: Target to discover and obtain network information from.
Returns:
A set of found DHCP IP addresses.
"""
ips = set()

for lease_file in chain(
target.fs.path("/var/lib/NetworkManager").glob("*.lease*"),
target.fs.path("/var/lib/dhcp").glob("*.lease*"),
target.fs.path("/var/lib/dhclient").glob("*.lease*"),
):
lease_text = lease_file.read_text()

if "lease {" in lease_text:
for line in lease_text.split("\n"):
if "fixed-address" in line:
ips.add(line.split(" ")[-1].strip(";"))

elif "ADDRESS=" in lease_text:
lease = configutil.parse(lease_file, hint="env")
if ip := lease.get("ADDRESS"):
ips.add(ip)

return ips


def should_ignore_ip(ip: str) -> bool:
for i in IGNORED_IPS:
if ip.startswith(i):
Expand Down
21 changes: 7 additions & 14 deletions dissect/target/plugins/os/windows/log/mssql.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class MssqlPlugin(Plugin):

__namespace__ = "mssql"

MSSQL_KEY = "HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server"
MSSQL_KEY_GLOB = "HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\MSSQL*.*"
FILE_GLOB = "ERRORLOG*"

def __init__(self, target: Target):
Expand All @@ -44,7 +44,7 @@ def __init__(self, target: Target):

def check_compatible(self) -> None:
if not self.instances:
raise UnsupportedPluginError("System does not seem to be running SQL Server")
raise UnsupportedPluginError("No Microsoft SQL Server instances have been found")

@export(record=MssqlErrorlogRecord)
def errorlog(self) -> Iterator[MssqlErrorlogRecord]:
Expand Down Expand Up @@ -89,15 +89,8 @@ def errorlog(self) -> Iterator[MssqlErrorlogRecord]:

buf += line

def _find_instances(self) -> list[str, TargetPath]:
instances = []

for subkey in self.target.registry.key(self.MSSQL_KEY).subkeys():
if subkey.name.startswith("MSSQL") and "." in subkey.name:
instances.append(
(
subkey.name,
self.target.fs.path(subkey.subkey("SQLServerAgent").value("ErrorLogFile").value).parent,
)
)
return instances
def _find_instances(self) -> set[str, TargetPath]:
return {
(subkey.name, self.target.fs.path(subkey.subkey("SQLServerAgent").value("ErrorLogFile").value).parent)
for subkey in self.target.registry.glob_ext(self.MSSQL_KEY_GLOB)
}
55 changes: 55 additions & 0 deletions tests/plugins/os/unix/test_ips.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,58 @@ def test_regression_ips_unique_strings(target_unix: Target, fs_unix: VirtualFile

assert len(target_unix.ips) == 1
assert target_unix.ips == ["1.2.3.4"]


def test_ips_dhcp_lease_files(target_unix: Target, fs_unix: VirtualFilesystem) -> None:
"""Test if we can detect DHCP lease files from NetworkManager and dhclient."""

lease1 = """
# This is private data. Do not parse.
ADDRESS=1.2.3.4
"""

lease2 = """
lease {
interface "eth0";
fixed-address 9.0.1.2;
option dhcp-lease-time 13337;
option routers 0.0.0.0;
option host-name "hostname";
renew 1 2023/12/31 13:37:00;
rebind 2 2023/01/01 01:00:00;
expire 3 2024/01/01 13:37:00;
# real leases contain more key/value pairs
}
lease {
interface "eth0";
fixed-address 5.6.7.8;
option dhcp-lease-time 13337;
option routers 0.0.0.0;
option host-name "hostname";
renew 1 2024/12/31 13:37:00;
rebind 2 2024/01/01 01:00:00;
expire 3 2025/01/01 13:37:00;
# real leases contain more key/value pairs
}
"""

lease3 = """
some-other "value";
lease {
interface "eth1";
fixed-address 3.4.5.6;
}
"""

fs_unix.map_file_fh("/var/lib/NetworkManager/internal-uuid-eth0.lease", BytesIO(textwrap.dedent(lease1).encode()))
fs_unix.map_file_fh("/var/lib/dhcp/dhclient.leases", BytesIO(textwrap.dedent(lease2).encode()))
fs_unix.map_file_fh("/var/lib/dhclient/dhclient.eth0.leases", BytesIO(textwrap.dedent(lease3).encode()))

syslog = "Apr 4 13:37:04 localhost dhclient[4]: bound to 1.3.3.7 -- renewal in 1337 seconds."
fs_unix.map_file_fh("/var/log/syslog", BytesIO(textwrap.dedent(syslog).encode()))

target_unix.add_plugin(LinuxPlugin)

# tests if we did not call :func:`parse_unix_dhcp_log_messages` since :func:`parse_unix_dhcp_leases` has results.
assert len(target_unix.ips) == 4
assert sorted(target_unix.ips) == sorted(["1.2.3.4", "5.6.7.8", "9.0.1.2", "3.4.5.6"])

0 comments on commit 0389348

Please sign in to comment.