Added system info collectors as plugins and the first plugin - EnvironmentCollector
This commit is contained in:
parent
974e2205d1
commit
c0331f84ff
|
@ -1,3 +1,7 @@
|
||||||
|
UNKNOWN = "Unknown"
|
||||||
ON_PREMISE = "On Premise"
|
ON_PREMISE = "On Premise"
|
||||||
AZURE = "Azure"
|
AZURE = "Azure"
|
||||||
AWS = "AWS"
|
AWS = "AWS"
|
||||||
|
GCP = "GCP"
|
||||||
|
|
||||||
|
ALL_ENV_NAMES = [UNKNOWN, ON_PREMISE, AZURE, AWS, GCP]
|
||||||
|
|
|
@ -125,6 +125,7 @@ class Configuration(object):
|
||||||
|
|
||||||
finger_classes = []
|
finger_classes = []
|
||||||
exploiter_classes = []
|
exploiter_classes = []
|
||||||
|
system_info_collectors_classes = ["EnvironmentCollector"]
|
||||||
|
|
||||||
# how many victims to look for in a single scan iteration
|
# how many victims to look for in a single scan iteration
|
||||||
victims_max_find = 100
|
victims_max_find = 100
|
||||||
|
|
|
@ -9,6 +9,7 @@ from infection_monkey.network.info import get_host_subnets
|
||||||
from infection_monkey.system_info.aws_collector import AwsCollector
|
from infection_monkey.system_info.aws_collector import AwsCollector
|
||||||
from infection_monkey.system_info.azure_cred_collector import AzureCollector
|
from infection_monkey.system_info.azure_cred_collector import AzureCollector
|
||||||
from infection_monkey.system_info.netstat_collector import NetstatCollector
|
from infection_monkey.system_info.netstat_collector import NetstatCollector
|
||||||
|
from system_info.system_info_collectors_handler import SystemInfoCollectorsHandler
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -61,12 +62,16 @@ class InfoCollector(object):
|
||||||
self.info = {}
|
self.info = {}
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
|
# Collect all hardcoded
|
||||||
self.get_hostname()
|
self.get_hostname()
|
||||||
self.get_process_list()
|
self.get_process_list()
|
||||||
self.get_network_info()
|
self.get_network_info()
|
||||||
self.get_azure_info()
|
self.get_azure_info()
|
||||||
self.get_aws_info()
|
self.get_aws_info()
|
||||||
|
|
||||||
|
# Collect all plugins
|
||||||
|
SystemInfoCollectorsHandler().execute_all_configured()
|
||||||
|
|
||||||
def get_hostname(self):
|
def get_hostname(self):
|
||||||
"""
|
"""
|
||||||
Adds the fully qualified computer hostname to the system information.
|
Adds the fully qualified computer hostname to the system information.
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""
|
||||||
|
This package holds all the dynamic (plugin) collectors
|
||||||
|
"""
|
|
@ -11,7 +11,7 @@ class SystemInfoCollector(Plugin):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def should_run(class_name) -> bool:
|
def should_run(class_name) -> bool:
|
||||||
return class_name in WormConfiguration.system_info_collectors
|
return class_name in WormConfiguration.system_info_collectors_classes
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def base_package_file():
|
def base_package_file():
|
||||||
|
|
|
@ -10,7 +10,7 @@ PATH_TO_COLLECTORS = "infection_monkey.system_info.collectors."
|
||||||
|
|
||||||
|
|
||||||
# TODO Add new collectors to config and config schema
|
# TODO Add new collectors to config and config schema
|
||||||
class SystemInfo(object):
|
class SystemInfoCollectorsHandler(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.collectors_list = self.config_to_collectors_list()
|
self.collectors_list = self.config_to_collectors_list()
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@ class SystemInfo(object):
|
||||||
LOG.error("Collector {} failed. Error info: {}".format(collector.name, e))
|
LOG.error("Collector {} failed. Error info: {}".format(collector.name, e))
|
||||||
LOG.info("All system info collectors executed. Total {} executed, out of which {} collected successfully.".
|
LOG.info("All system info collectors executed. Total {} executed, out of which {} collected successfully.".
|
||||||
format(len(self.collectors_list), successful_collections))
|
format(len(self.collectors_list), successful_collections))
|
||||||
# TODO Send SystemInfoTelem()
|
|
||||||
|
SystemInfoTelem({"collectors": system_info_telemetry}).send()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def config_to_collectors_list() -> Sequence[SystemInfoCollector]:
|
def config_to_collectors_list() -> Sequence[SystemInfoCollector]:
|
|
@ -9,6 +9,7 @@ from monkey_island.cc.models.monkey_ttl import MonkeyTtl, create_monkey_ttl_docu
|
||||||
from monkey_island.cc.consts import DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS
|
from monkey_island.cc.consts import DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS
|
||||||
from monkey_island.cc.models.command_control_channel import CommandControlChannel
|
from monkey_island.cc.models.command_control_channel import CommandControlChannel
|
||||||
from monkey_island.cc.utils import local_ip_addresses
|
from monkey_island.cc.utils import local_ip_addresses
|
||||||
|
from common.cloud import environment_names
|
||||||
|
|
||||||
MAX_MONKEYS_AMOUNT_TO_CACHE = 100
|
MAX_MONKEYS_AMOUNT_TO_CACHE = 100
|
||||||
|
|
||||||
|
@ -42,6 +43,9 @@ class Monkey(Document):
|
||||||
ttl_ref = ReferenceField(MonkeyTtl)
|
ttl_ref = ReferenceField(MonkeyTtl)
|
||||||
tunnel = ReferenceField("self")
|
tunnel = ReferenceField("self")
|
||||||
command_control_channel = EmbeddedDocumentField(CommandControlChannel)
|
command_control_channel = EmbeddedDocumentField(CommandControlChannel)
|
||||||
|
|
||||||
|
# Environment related fields
|
||||||
|
environment = StringField(default=environment_names.UNKNOWN, choices=environment_names.ALL_ENV_NAMES)
|
||||||
aws_instance_id = StringField(required=False) # This field only exists when the monkey is running on an AWS
|
aws_instance_id = StringField(required=False) # This field only exists when the monkey is running on an AWS
|
||||||
|
|
||||||
# instance. See https://github.com/guardicore/monkey/issues/426.
|
# instance. See https://github.com/guardicore/monkey/issues/426.
|
||||||
|
@ -55,7 +59,8 @@ class Monkey(Document):
|
||||||
raise MonkeyNotFoundError("info: {0} | id: {1}".format(ex, str(db_id)))
|
raise MonkeyNotFoundError("info: {0} | id: {1}".format(ex, str(db_id)))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_single_monkey_by_guid(monkey_guid):
|
# See https://www.python.org/dev/peps/pep-0484/#forward-references
|
||||||
|
def get_single_monkey_by_guid(monkey_guid) -> 'Monkey':
|
||||||
try:
|
try:
|
||||||
return Monkey.objects.get(guid=monkey_guid)
|
return Monkey.objects.get(guid=monkey_guid)
|
||||||
except DoesNotExist as ex:
|
except DoesNotExist as ex:
|
||||||
|
|
|
@ -99,6 +99,20 @@ SCHEMA = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"system_info_collectors_classes": {
|
||||||
|
"title": "System Information Collectors",
|
||||||
|
"type": "string",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"EnvironmentCollector"
|
||||||
|
],
|
||||||
|
"title": "Which Environment this machine is on (on prem/cloud)",
|
||||||
|
"attack_techniques": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
"post_breach_acts": {
|
"post_breach_acts": {
|
||||||
"title": "Post breach actions",
|
"title": "Post breach actions",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -433,6 +447,18 @@ SCHEMA = {
|
||||||
"attack_techniques": ["T1003"],
|
"attack_techniques": ["T1003"],
|
||||||
"description": "Determines whether to use Mimikatz"
|
"description": "Determines whether to use Mimikatz"
|
||||||
},
|
},
|
||||||
|
"system_info_collectors_classes": {
|
||||||
|
"title": "System info collectors",
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": True,
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/system_info_collectors_classes"
|
||||||
|
},
|
||||||
|
"default": [
|
||||||
|
"EnvironmentCollector"
|
||||||
|
],
|
||||||
|
"description": "Determines which system information collectors will collect information."
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"life_cycle": {
|
"life_cycle": {
|
||||||
|
|
|
@ -5,6 +5,7 @@ from monkey_island.cc.models import Monkey
|
||||||
from monkey_island.cc.services import mimikatz_utils
|
from monkey_island.cc.services import mimikatz_utils
|
||||||
from monkey_island.cc.services.node import NodeService
|
from monkey_island.cc.services.node import NodeService
|
||||||
from monkey_island.cc.services.config import ConfigService
|
from monkey_island.cc.services.config import ConfigService
|
||||||
|
from monkey_island.cc.services.telemetry.processing.system_info_collectors.environment import process_environment_telemetry
|
||||||
from monkey_island.cc.services.telemetry.zero_trust_tests.antivirus_existence import test_antivirus_existence
|
from monkey_island.cc.services.telemetry.zero_trust_tests.antivirus_existence import test_antivirus_existence
|
||||||
from monkey_island.cc.services.wmi_handler import WMIHandler
|
from monkey_island.cc.services.wmi_handler import WMIHandler
|
||||||
from monkey_island.cc.encryptor import encryptor
|
from monkey_island.cc.encryptor import encryptor
|
||||||
|
@ -20,6 +21,7 @@ def process_system_info_telemetry(telemetry_json):
|
||||||
process_aws_data,
|
process_aws_data,
|
||||||
update_db_with_new_hostname,
|
update_db_with_new_hostname,
|
||||||
test_antivirus_existence,
|
test_antivirus_existence,
|
||||||
|
process_environment_telemetry
|
||||||
]
|
]
|
||||||
|
|
||||||
# Calling safe_process_telemetry so if one of the stages fail, we log and move on instead of failing the rest of
|
# Calling safe_process_telemetry so if one of the stages fail, we log and move on instead of failing the rest of
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from monkey_island.cc.models.monkey import Monkey
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def process_environment_telemetry(telemetry_json):
|
||||||
|
if "EnvironmentCollector" in telemetry_json["data"]["collectors"]:
|
||||||
|
env = telemetry_json["data"]["collectors"]["EnvironmentCollector"]["environment"]
|
||||||
|
relevant_monkey = Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid'])
|
||||||
|
relevant_monkey.environment = env
|
||||||
|
relevant_monkey.save()
|
||||||
|
logger.debug("Updated Monkey {} with env {}".format(str(relevant_monkey), env))
|
Loading…
Reference in New Issue