Agent: refactor ssh fingerprinter to fit the new model
This commit is contained in:
parent
1dc08e2087
commit
1c7ec9c41f
|
@ -89,13 +89,13 @@ class MockMaster(IMaster):
|
|||
machine_1 = self._hosts["10.0.0.1"]
|
||||
machine_3 = self._hosts["10.0.0.3"]
|
||||
|
||||
self._puppet.fingerprint("SMBFinger", machine_1, None, None)
|
||||
self._puppet.fingerprint("SMBFinger", machine_1, None, None, None)
|
||||
self._telemetry_messenger.send_telemetry(ScanTelem(machine_1))
|
||||
|
||||
self._puppet.fingerprint("SMBFinger", machine_3, None, None)
|
||||
self._puppet.fingerprint("SMBFinger", machine_3, None, None, None)
|
||||
self._telemetry_messenger.send_telemetry(ScanTelem(machine_3))
|
||||
|
||||
self._puppet.fingerprint("HTTPFinger", machine_3, None, None)
|
||||
self._puppet.fingerprint("HTTPFinger", machine_3, None, None, None)
|
||||
self._telemetry_messenger.send_telemetry(ScanTelem(machine_3))
|
||||
logger.info("Finished running fingerprinters on potential victims")
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ from infection_monkey.network.http_fingerprinter import HTTPFingerprinter
|
|||
from infection_monkey.network.info import get_local_network_interfaces
|
||||
from infection_monkey.network.mssql_fingerprinter import MSSQLFingerprinter
|
||||
from infection_monkey.network.smb_fingerprinter import SMBFingerprinter
|
||||
from infection_monkey.network.ssh_fingerprinter import SSHFingerprinter
|
||||
from infection_monkey.payload.ransomware.ransomware_payload import RansomwarePayload
|
||||
from infection_monkey.puppet.puppet import Puppet
|
||||
from infection_monkey.system_singleton import SystemSingleton
|
||||
|
@ -192,6 +193,7 @@ class InfectionMonkey:
|
|||
puppet.load_plugin("http", HTTPFingerprinter(), PluginType.FINGERPRINTER)
|
||||
puppet.load_plugin("mssql", MSSQLFingerprinter(), PluginType.FINGERPRINTER)
|
||||
puppet.load_plugin("smb", SMBFingerprinter(), PluginType.FINGERPRINTER)
|
||||
puppet.load_plugin("ssh", SSHFingerprinter(), PluginType.FINGERPRINTER)
|
||||
|
||||
puppet.load_plugin("ransomware", RansomwarePayload(), PluginType.PAYLOAD)
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import re
|
||||
from typing import Dict, Tuple, Union
|
||||
|
||||
from infection_monkey.i_puppet import FingerprintData, IFingerprinter, PortScanData
|
||||
|
||||
SSH_PORT = 22
|
||||
SSH_REGEX = r"SSH-\d\.\d-OpenSSH"
|
||||
LINUX_DIST_SSH = ["ubuntu", "debian"]
|
||||
|
||||
|
||||
class SSHFingerprinter(IFingerprinter):
|
||||
_SCANNED_SERVICE = "SSH"
|
||||
|
||||
def __init__(self):
|
||||
self._banner_regex = re.compile(SSH_REGEX, re.IGNORECASE)
|
||||
|
||||
def get_host_fingerprint(
|
||||
self, host: str, _ping_scan_data, port_scan_data: Dict[int, PortScanData], _options
|
||||
) -> FingerprintData:
|
||||
os_type = None
|
||||
os_version = None
|
||||
services = {}
|
||||
|
||||
for ps_data in list(port_scan_data.values()):
|
||||
if ps_data.banner and self._banner_regex.search(ps_data.banner):
|
||||
os_type, os_version = self._get_host_os(ps_data.banner)
|
||||
services[f"tcp-{ps_data.port}"] = {
|
||||
"display_name": SSHFingerprinter._SCANNED_SERVICE,
|
||||
"port": ps_data.port,
|
||||
"name": "ssh",
|
||||
}
|
||||
return FingerprintData(os_type, os_version, services)
|
||||
|
||||
@staticmethod
|
||||
def _get_host_os(banner) -> Tuple[Union[str, None], Union[str, None]]:
|
||||
os = None
|
||||
os_version = None
|
||||
for dist in LINUX_DIST_SSH:
|
||||
if banner.lower().find(dist) != -1:
|
||||
os_version = banner.split(" ").pop().strip()
|
||||
os = "linux"
|
||||
|
||||
return os, os_version
|
|
@ -1,54 +0,0 @@
|
|||
import re
|
||||
|
||||
import infection_monkey.config
|
||||
from infection_monkey.network.HostFinger import HostFinger
|
||||
from infection_monkey.network.tools import check_tcp_port
|
||||
|
||||
SSH_PORT = 22
|
||||
SSH_SERVICE_DEFAULT = "tcp-22"
|
||||
SSH_REGEX = r"SSH-\d\.\d-OpenSSH"
|
||||
TIMEOUT = 10
|
||||
BANNER_READ = 1024
|
||||
LINUX_DIST_SSH = ["ubuntu", "debian"]
|
||||
|
||||
|
||||
class SSHFinger(HostFinger):
|
||||
_SCANNED_SERVICE = "SSH"
|
||||
|
||||
def __init__(self):
|
||||
self._config = infection_monkey.config.WormConfiguration
|
||||
self._banner_regex = re.compile(SSH_REGEX, re.IGNORECASE)
|
||||
|
||||
@staticmethod
|
||||
def _banner_match(service, host, banner):
|
||||
host.services[service]["name"] = "ssh"
|
||||
for dist in LINUX_DIST_SSH:
|
||||
if banner.lower().find(dist) != -1:
|
||||
host.os["type"] = "linux"
|
||||
os_version = banner.split(" ").pop().strip()
|
||||
if "version" not in host.os:
|
||||
host.os["version"] = os_version
|
||||
|
||||
break
|
||||
|
||||
def get_host_fingerprint(self, host):
|
||||
|
||||
for name, data in list(host.services.items()):
|
||||
banner = data.get("banner", "")
|
||||
if self._banner_regex.search(banner):
|
||||
self._banner_match(name, host, banner)
|
||||
host.services[SSH_SERVICE_DEFAULT]["display_name"] = self._SCANNED_SERVICE
|
||||
return
|
||||
|
||||
is_open, banner = check_tcp_port(host.ip_addr, SSH_PORT, TIMEOUT, True)
|
||||
|
||||
if is_open:
|
||||
self.init_service(host.services, SSH_SERVICE_DEFAULT, SSH_PORT)
|
||||
|
||||
if banner:
|
||||
host.services[SSH_SERVICE_DEFAULT]["banner"] = banner
|
||||
if self._banner_regex.search(banner):
|
||||
self._banner_match(SSH_SERVICE_DEFAULT, host, banner)
|
||||
return True
|
||||
|
||||
return False
|
|
@ -0,0 +1,95 @@
|
|||
import pytest
|
||||
|
||||
from infection_monkey.i_puppet import FingerprintData, PortScanData, PortStatus
|
||||
from infection_monkey.network.ssh_fingerprinter import SSHFingerprinter
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ssh_fingerprinter():
|
||||
return SSHFingerprinter()
|
||||
|
||||
|
||||
def test_no_ssh_ports_open(ssh_fingerprinter):
|
||||
port_scan_data = {
|
||||
22: PortScanData(22, PortStatus.CLOSED, "", "tcp-22"),
|
||||
123: PortScanData(123, PortStatus.OPEN, "", "tcp-123"),
|
||||
443: PortScanData(443, PortStatus.CLOSED, "", "tcp-443"),
|
||||
}
|
||||
results = ssh_fingerprinter.get_host_fingerprint("127.0.0.1", None, port_scan_data, None)
|
||||
|
||||
assert results == FingerprintData(None, None, {})
|
||||
|
||||
|
||||
def test_no_os(ssh_fingerprinter):
|
||||
port_scan_data = {
|
||||
22: PortScanData(22, PortStatus.OPEN, "SSH-2.0-OpenSSH_8.2p1", "tcp-22"),
|
||||
2222: PortScanData(2222, PortStatus.OPEN, "SSH-2.0-OpenSSH_8.2p1", "tcp-2222"),
|
||||
443: PortScanData(443, PortStatus.CLOSED, "", "tcp-443"),
|
||||
8080: PortScanData(8080, PortStatus.CLOSED, "", "tcp-8080"),
|
||||
}
|
||||
results = ssh_fingerprinter.get_host_fingerprint("127.0.0.1", None, port_scan_data, None)
|
||||
|
||||
assert results == FingerprintData(
|
||||
None,
|
||||
None,
|
||||
{
|
||||
"tcp-22": {
|
||||
"display_name": "SSH",
|
||||
"port": 22,
|
||||
"name": "ssh",
|
||||
},
|
||||
"tcp-2222": {
|
||||
"display_name": "SSH",
|
||||
"port": 2222,
|
||||
"name": "ssh",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_ssh_os(ssh_fingerprinter):
|
||||
port_scan_data = {
|
||||
22: PortScanData(22, PortStatus.OPEN, "SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.2", "tcp-22"),
|
||||
443: PortScanData(443, PortStatus.CLOSED, "", "tcp-443"),
|
||||
8080: PortScanData(8080, PortStatus.CLOSED, "", "tcp-8080"),
|
||||
}
|
||||
results = ssh_fingerprinter.get_host_fingerprint("127.0.0.1", None, port_scan_data, None)
|
||||
|
||||
assert results == FingerprintData(
|
||||
"linux",
|
||||
"Ubuntu-4ubuntu0.2",
|
||||
{
|
||||
"tcp-22": {
|
||||
"display_name": "SSH",
|
||||
"port": 22,
|
||||
"name": "ssh",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_multiple_os(ssh_fingerprinter):
|
||||
port_scan_data = {
|
||||
22: PortScanData(22, PortStatus.OPEN, "SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.2", "tcp-22"),
|
||||
2222: PortScanData(2222, PortStatus.OPEN, "SSH-2.0-OpenSSH_8.2p1 Debian", "tcp-2222"),
|
||||
443: PortScanData(443, PortStatus.CLOSED, "", "tcp-443"),
|
||||
8080: PortScanData(8080, PortStatus.CLOSED, "", "tcp-8080"),
|
||||
}
|
||||
results = ssh_fingerprinter.get_host_fingerprint("127.0.0.1", None, port_scan_data, None)
|
||||
|
||||
assert results == FingerprintData(
|
||||
"linux",
|
||||
"Debian",
|
||||
{
|
||||
"tcp-22": {
|
||||
"display_name": "SSH",
|
||||
"port": 22,
|
||||
"name": "ssh",
|
||||
},
|
||||
"tcp-2222": {
|
||||
"display_name": "SSH",
|
||||
"port": 2222,
|
||||
"name": "ssh",
|
||||
},
|
||||
},
|
||||
)
|
Loading…
Reference in New Issue