forked from p15670423/monkey
Island: Simplify the report of scanned machines
This commit is contained in:
parent
9a82e46799
commit
3d27e42ff3
|
@ -1,8 +1,8 @@
|
||||||
import functools
|
import functools
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import logging
|
import logging
|
||||||
from itertools import chain, filterfalse, product, tee
|
from itertools import chain, product
|
||||||
from typing import Iterable, List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from common.network.network_range import NetworkRange
|
from common.network.network_range import NetworkRange
|
||||||
from common.network.network_utils import get_my_ip_addresses_legacy, get_network_interfaces
|
from common.network.network_utils import get_my_ip_addresses_legacy, get_network_interfaces
|
||||||
|
@ -35,7 +35,6 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ReportService:
|
class ReportService:
|
||||||
|
|
||||||
_aws_service: Optional[AWSService] = None
|
_aws_service: Optional[AWSService] = None
|
||||||
_agent_configuration_repository: Optional[IAgentConfigurationRepository] = None
|
_agent_configuration_repository: Optional[IAgentConfigurationRepository] = None
|
||||||
_credentials_repository: Optional[ICredentialsRepository] = None
|
_credentials_repository: Optional[ICredentialsRepository] = None
|
||||||
|
@ -113,58 +112,42 @@ class ReportService:
|
||||||
def get_scanned():
|
def get_scanned():
|
||||||
formatted_nodes = []
|
formatted_nodes = []
|
||||||
|
|
||||||
machines = ReportService.get_all_machines()
|
machines = ReportService._machine_repository.get_machines()
|
||||||
|
|
||||||
for machine in machines:
|
for machine in machines:
|
||||||
# This information should be evident from the map, not sure a table/list is a good way
|
accessible_from = ReportService.get_scanners_of_machine(machine)
|
||||||
# to display it anyways
|
if accessible_from:
|
||||||
addresses = [str(iface.ip) for iface in machine.network_interfaces]
|
|
||||||
accessible_machines = [
|
|
||||||
m.hostname for m in ReportService.get_accessible_machines(machine)
|
|
||||||
]
|
|
||||||
formatted_nodes.append(
|
formatted_nodes.append(
|
||||||
{
|
{
|
||||||
"label": machine.hostname,
|
"hostname": machine.hostname,
|
||||||
"ip_addresses": addresses,
|
"ip_addresses": machine.network_interfaces,
|
||||||
"accessible_from_nodes": accessible_machines,
|
"accessible_from_nodes": accessible_from,
|
||||||
"services": [],
|
|
||||||
"domain_name": "",
|
"domain_name": "",
|
||||||
"pba_results": "None",
|
# TODO add services
|
||||||
|
"services": [],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info("Scanned nodes generated for reporting")
|
|
||||||
|
|
||||||
return formatted_nodes
|
return formatted_nodes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_accessible_machines(cls, machine: Machine):
|
def get_scanners_of_machine(cls, machine: Machine) -> List[Machine]:
|
||||||
if cls._node_repository is None:
|
if not cls._node_repository:
|
||||||
raise RuntimeError("Node repository does not exist")
|
raise RuntimeError("Node repository does not exist")
|
||||||
elif cls._machine_repository is None:
|
if not cls._machine_repository:
|
||||||
raise RuntimeError("Machine repository does not exist")
|
raise RuntimeError("Machine repository does not exist")
|
||||||
|
|
||||||
nodes = cls._node_repository.get_nodes()
|
nodes = cls._node_repository.get_nodes()
|
||||||
machine_iter = (node for node in nodes if node.machine_id == machine.id)
|
scanner_machines = set()
|
||||||
accessible_machines = set()
|
for node in nodes:
|
||||||
for source in machine_iter:
|
for dest, conn in node.connections.items():
|
||||||
for dest, conn in source.connections.items():
|
if CommunicationType.SCANNED in conn and dest == machine.id:
|
||||||
if CommunicationType.SCANNED in conn:
|
scanner_machine = ReportService._machine_repository.get_machine_by_id(
|
||||||
accessible_machines.add(dest)
|
node.machine_id
|
||||||
|
)
|
||||||
|
scanner_machines.add(scanner_machine)
|
||||||
|
|
||||||
return [cls._machine_repository.get_machine_by_id(id) for id in accessible_machines]
|
return list(scanner_machines)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_all_machines(cls) -> Iterable[Machine]:
|
|
||||||
if cls._machine_repository is None:
|
|
||||||
raise RuntimeError("Machine repository does not exist")
|
|
||||||
machines = cls._machine_repository.get_machines()
|
|
||||||
t1, t2 = tee(machines)
|
|
||||||
|
|
||||||
def is_island(machine: Machine):
|
|
||||||
return machine.island
|
|
||||||
|
|
||||||
return chain(filter(is_island, t1), filterfalse(is_island, t2))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def process_exploit(exploit) -> ExploiterReportInfo:
|
def process_exploit(exploit) -> ExploiterReportInfo:
|
||||||
|
|
|
@ -1,34 +1,77 @@
|
||||||
from ipaddress import IPv4Interface
|
from ipaddress import IPv4Interface
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from monkey_island.cc.models import CommunicationType, Machine, Node
|
from monkey_island.cc.models import CommunicationType, Machine, Node
|
||||||
|
from monkey_island.cc.services.reporting.report import ReportService
|
||||||
|
|
||||||
ISLAND_MACHINE = Machine(
|
ISLAND_MACHINE = Machine(
|
||||||
id=99,
|
id=99,
|
||||||
island=True,
|
island=True,
|
||||||
|
hostname="Island",
|
||||||
hardware_id=5,
|
hardware_id=5,
|
||||||
network_interfaces=[IPv4Interface("10.10.10.99/24")],
|
network_interfaces=[IPv4Interface("10.10.10.99/24")],
|
||||||
)
|
)
|
||||||
|
|
||||||
MACHINE_A = Machine(
|
MACHINE_1 = Machine(
|
||||||
id=1,
|
id=1,
|
||||||
hardware_id=9,
|
hardware_id=9,
|
||||||
|
hostname="machine_1",
|
||||||
network_interfaces=[IPv4Interface("10.10.10.1/24")],
|
network_interfaces=[IPv4Interface("10.10.10.1/24")],
|
||||||
)
|
)
|
||||||
|
|
||||||
MACHINE_B = Machine(
|
MACHINE_2 = Machine(
|
||||||
id=2,
|
id=2,
|
||||||
hardware_id=9,
|
hardware_id=9,
|
||||||
network_interfaces=[IPv4Interface("10.10.10.2/24")],
|
network_interfaces=[IPv4Interface("10.10.10.2/24")],
|
||||||
)
|
)
|
||||||
|
|
||||||
MACHINE_C = Machine(
|
MACHINE_3 = Machine(
|
||||||
id=3,
|
id=3,
|
||||||
hardware_id=9,
|
hardware_id=9,
|
||||||
network_interfaces=[IPv4Interface("10.10.10.3/24")],
|
network_interfaces=[IPv4Interface("10.10.10.3/24")],
|
||||||
)
|
)
|
||||||
|
|
||||||
NODES = [
|
NODES = [
|
||||||
Node(machine_id=1, connections={"2": {CommunicationType.EXPLOITED}}),
|
Node(
|
||||||
Node(machine_id=99, connections={"1": {CommunicationType.SCANNED}}),
|
machine_id=1,
|
||||||
Node(machine_id=3, connections={"99": {CommunicationType.CC}}),
|
connections={"2": frozenset([CommunicationType.EXPLOITED, CommunicationType.SCANNED])},
|
||||||
|
),
|
||||||
|
Node(machine_id=99, connections={"1": frozenset([CommunicationType.SCANNED])}),
|
||||||
|
Node(
|
||||||
|
machine_id=3,
|
||||||
|
connections={"99": frozenset([CommunicationType.CC, CommunicationType.EXPLOITED])},
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
MACHINES = [MACHINE_1, MACHINE_2, MACHINE_3, ISLAND_MACHINE]
|
||||||
|
|
||||||
|
EXPECTED_SCANNED_MACHINES = [
|
||||||
|
{
|
||||||
|
"hostname": MACHINE_1.hostname,
|
||||||
|
"ip_addresses": MACHINE_1.network_interfaces,
|
||||||
|
"accessible_from_nodes": [ISLAND_MACHINE],
|
||||||
|
"services": [],
|
||||||
|
"domain_name": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hostname": MACHINE_2.hostname,
|
||||||
|
"ip_addresses": MACHINE_2.network_interfaces,
|
||||||
|
"accessible_from_nodes": [MACHINE_1],
|
||||||
|
"services": [],
|
||||||
|
"domain_name": "",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_machine_by_id(machine_id):
|
||||||
|
return [machine for machine in MACHINES if machine_id == machine.id][0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_scanned():
|
||||||
|
ReportService._node_repository = MagicMock()
|
||||||
|
ReportService._node_repository.get_nodes.return_value = NODES
|
||||||
|
ReportService._machine_repository = MagicMock()
|
||||||
|
ReportService._machine_repository.get_machines.return_value = MACHINES
|
||||||
|
ReportService._machine_repository.get_machine_by_id = get_machine_by_id
|
||||||
|
scanned = ReportService.get_scanned()
|
||||||
|
assert scanned == EXPECTED_SCANNED_MACHINES
|
||||||
|
|
Loading…
Reference in New Issue