Merge pull request #1600 from guardicore/1537-remove-max-iters

Remove max iterations and timeout between iterations options
This commit is contained in:
Mike Salvatore 2021-11-19 08:08:10 -05:00 committed by GitHub
commit f3b7803955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 148 deletions

View File

@ -17,13 +17,13 @@
"type": "snippet", "type": "snippet",
"path": "monkey/infection_monkey/config.py", "path": "monkey/infection_monkey/config.py",
"comments": [], "comments": [],
"firstLineNumber": 124, "firstLineNumber": 103,
"lines": [ "lines": [
" exploiter_classes = []", " exploiter_classes = []",
" system_info_collector_classes = []", " system_info_collector_classes = []",
" ", " ",
"* # how many victims to look for in a single scan iteration\r", "* # how many victims to look for in a single scan iteration",
"* victims_max_find = 100\r", "* victims_max_find = 100",
" ", " ",
" # how many victims to exploit before stopping", " # how many victims to exploit before stopping",
" victims_max_exploit = 100" " victims_max_exploit = 100"
@ -35,23 +35,23 @@
"comments": [], "comments": [],
"firstLineNumber": 220, "firstLineNumber": 220,
"lines": [ "lines": [
" if not self._keep_running or not WormConfiguration.alive:", " if not WormConfiguration.alive:",
" break", " logger.info(\"Marked not alive from configuration\")",
" ", " ",
"* machines = self._network.get_victim_machines(", "* machines = self._network.get_victim_machines(",
"* max_find=WormConfiguration.victims_max_find,", "* max_find=WormConfiguration.victims_max_find,",
"* stop_callback=ControlClient.check_for_stop,", "* stop_callback=ControlClient.check_for_stop,",
"* )", "* )",
" is_empty = True", " for machine in machines:",
" for machine in machines:", " if ControlClient.check_for_stop():",
" if ControlClient.check_for_stop():" " break"
] ]
}, },
{ {
"type": "snippet", "type": "snippet",
"path": "monkey/monkey_island/cc/services/config_schema/internal.py", "path": "monkey/monkey_island/cc/services/config_schema/internal.py",
"comments": [], "comments": [],
"firstLineNumber": 42, "firstLineNumber": 28,
"lines": [ "lines": [
" \"title\": \"Monkey\",", " \"title\": \"Monkey\",",
" \"type\": \"object\",", " \"type\": \"object\",",
@ -74,13 +74,13 @@
} }
], ],
"symbols": {}, "symbols": {},
"file_version": "2.0.1", "file_version": "2.0.3",
"meta": { "meta": {
"app_version": "0.4.9-1", "app_version": "0.6.6-2",
"file_blobs": { "file_blobs": {
"monkey/infection_monkey/config.py": "0bede1c57949987f5c8025bd9b8f7aa29d02a6af", "monkey/infection_monkey/config.py": "8f4984ba6563564343282765ab498efca5d89ba8",
"monkey/infection_monkey/monkey.py": "89d2fa8452dee70f6d2985a9bb452f0159ea8219", "monkey/infection_monkey/monkey.py": "4160a36e0e624404d77526472d51dd07bba49e5a",
"monkey/monkey_island/cc/services/config_schema/internal.py": "1ce1c864b1df332b65e16b4ce9ed533affd73f9c" "monkey/monkey_island/cc/services/config_schema/internal.py": "86318eaf19b9991a8af5de861a3eb085238e17a4"
} }
} }
} }

View File

@ -29,6 +29,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- Azure credential collector, because it was broken (not gathering credentials). #1535 - Azure credential collector, because it was broken (not gathering credentials). #1535
- Custom monkey directory name config option. #1537 - Custom monkey directory name config option. #1537
- Hostname system info collector. #1535 - Hostname system info collector. #1535
- Max iterations and timeout between iterations config options. #1600
### Fixed ### Fixed
- A bug in network map page that caused delay of telemetry log loading. #1545 - A bug in network map page that caused delay of telemetry log loading. #1545

View File

@ -99,12 +99,6 @@ class Configuration(object):
# sets whether or not the monkey is alive. if false will stop scanning and exploiting # sets whether or not the monkey is alive. if false will stop scanning and exploiting
alive = True alive = True
# how long to wait between scan iterations
timeout_between_iterations = 100
# how many scan iterations to perform on each run
max_iterations = 1
finger_classes = [] finger_classes = []
exploiter_classes = [] exploiter_classes = []
system_info_collector_classes = [] system_info_collector_classes = []
@ -124,9 +118,6 @@ class Configuration(object):
# Configuration servers to try to connect to, in this order. # Configuration servers to try to connect to, in this order.
command_servers = ["192.0.2.0:5000"] command_servers = ["192.0.2.0:5000"]
# sets whether or not to retry failed hosts on next scan
retry_failed_explotation = True
keep_tunnel_open_time = 60 keep_tunnel_open_time = 60
########################### ###########################

View File

@ -43,7 +43,6 @@
"MSSQLFingerprint", "MSSQLFingerprint",
"ElasticFinger" "ElasticFinger"
], ],
"max_iterations": 3,
"monkey_log_path_windows": "%temp%\\~df1563.tmp", "monkey_log_path_windows": "%temp%\\~df1563.tmp",
"monkey_log_path_linux": "/tmp/user-1563", "monkey_log_path_linux": "/tmp/user-1563",
"ms08_067_exploit_attempts": 5, "ms08_067_exploit_attempts": 5,
@ -51,7 +50,6 @@
"ping_scan_timeout": 10000, "ping_scan_timeout": 10000,
"smb_download_timeout": 300, "smb_download_timeout": 300,
"smb_service_name": "InfectionMonkey", "smb_service_name": "InfectionMonkey",
"retry_failed_explotation": true,
"self_delete_in_cleanup": true, "self_delete_in_cleanup": true,
"skip_exploit_if_file_exist": false, "skip_exploit_if_file_exist": false,
"exploit_user_list": [], "exploit_user_list": [],
@ -77,7 +75,6 @@
7001, 7001,
8088 8088
], ],
"timeout_between_iterations": 10,
"victims_max_exploit": 100, "victims_max_exploit": 100,
"victims_max_find": 100, "victims_max_find": 100,
"post_breach_actions": [] "post_breach_actions": []

View File

@ -208,98 +208,80 @@ class InfectionMonkey(object):
raise PlannedShutdownException("Marked 'not alive' from configuration.") raise PlannedShutdownException("Marked 'not alive' from configuration.")
def propagate(self): def propagate(self):
for iteration_index in range(WormConfiguration.max_iterations): ControlClient.keepalive()
ControlClient.keepalive() ControlClient.load_control_config()
ControlClient.load_control_config()
self._network.initialize() self._network.initialize()
self._fingerprint = HostFinger.get_instances() self._fingerprint = HostFinger.get_instances()
self._exploiters = HostExploiter.get_classes() self._exploiters = HostExploiter.get_classes()
if not self._keep_running or not WormConfiguration.alive: if not WormConfiguration.alive:
logger.info("Marked not alive from configuration")
machines = self._network.get_victim_machines(
max_find=WormConfiguration.victims_max_find,
stop_callback=ControlClient.check_for_stop,
)
for machine in machines:
if ControlClient.check_for_stop():
break break
machines = self._network.get_victim_machines( for finger in self._fingerprint:
max_find=WormConfiguration.victims_max_find, logger.info(
stop_callback=ControlClient.check_for_stop, "Trying to get OS fingerprint from %r with module %s",
) machine,
is_empty = True finger.__class__.__name__,
for machine in machines:
if ControlClient.check_for_stop():
break
is_empty = False
for finger in self._fingerprint:
logger.info(
"Trying to get OS fingerprint from %r with module %s",
machine,
finger.__class__.__name__,
)
try:
finger.get_host_fingerprint(machine)
except BaseException as exc:
logger.error(
"Failed to run fingerprinter %s, exception %s"
% finger.__class__.__name__,
str(exc),
)
ScanTelem(machine).send()
# skip machines that we've already exploited
if machine in self._exploited_machines:
logger.debug("Skipping %r - already exploited", machine)
continue
elif machine in self._fail_exploitation_machines:
if WormConfiguration.retry_failed_explotation:
logger.debug("%r - exploitation failed before, trying again", machine)
else:
logger.debug("Skipping %r - exploitation failed before", machine)
continue
if self._monkey_tunnel:
self._monkey_tunnel.set_tunnel_for_host(machine)
if self._default_server:
if self._network.on_island(self._default_server):
machine.set_default_server(
get_interface_to_target(machine.ip_addr)
+ (":" + self._default_server_port if self._default_server_port else "")
)
else:
machine.set_default_server(self._default_server)
logger.debug(
"Default server for machine: %r set to %s"
% (machine, machine.default_server)
)
# Order exploits according to their type
self._exploiters = sorted(
self._exploiters, key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value
) )
host_exploited = False try:
for exploiter in [exploiter(machine) for exploiter in self._exploiters]: finger.get_host_fingerprint(machine)
if self.try_exploiting(machine, exploiter): except BaseException as exc:
host_exploited = True logger.error(
VictimHostTelem("T1210", ScanStatus.USED, machine=machine).send() "Failed to run fingerprinter %s, exception %s" % finger.__class__.__name__,
if exploiter.RUNS_AGENT_ON_SUCCESS: str(exc),
break # if adding machine to exploited, won't try other exploits )
# on it
if not host_exploited:
self._fail_exploitation_machines.add(machine)
VictimHostTelem("T1210", ScanStatus.SCANNED, machine=machine).send()
if not self._keep_running:
break
if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1): ScanTelem(machine).send()
time_to_sleep = WormConfiguration.timeout_between_iterations
logger.info("Sleeping %d seconds before next life cycle iteration", time_to_sleep)
time.sleep(time_to_sleep)
if self._keep_running and WormConfiguration.alive: # skip machines that we've already exploited
logger.info("Reached max iterations (%d)", WormConfiguration.max_iterations) if machine in self._exploited_machines:
elif not WormConfiguration.alive: logger.debug("Skipping %r - already exploited", machine)
continue
if self._monkey_tunnel:
self._monkey_tunnel.set_tunnel_for_host(machine)
if self._default_server:
if self._network.on_island(self._default_server):
machine.set_default_server(
get_interface_to_target(machine.ip_addr)
+ (":" + self._default_server_port if self._default_server_port else "")
)
else:
machine.set_default_server(self._default_server)
logger.debug(
"Default server for machine: %r set to %s" % (machine, machine.default_server)
)
# Order exploits according to their type
self._exploiters = sorted(
self._exploiters, key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value
)
host_exploited = False
for exploiter in [exploiter(machine) for exploiter in self._exploiters]:
if self.try_exploiting(machine, exploiter):
host_exploited = True
VictimHostTelem("T1210", ScanStatus.USED, machine=machine).send()
if exploiter.RUNS_AGENT_ON_SUCCESS:
break # if adding machine to exploited, won't try other exploits
# on it
if not host_exploited:
self._fail_exploitation_machines.add(machine)
VictimHostTelem("T1210", ScanStatus.SCANNED, machine=machine).send()
if not self._keep_running:
break
if not WormConfiguration.alive:
logger.info("Marked not alive from configuration") logger.info("Marked not alive from configuration")
def upgrade_to_64_if_needed(self): def upgrade_to_64_if_needed(self):

View File

@ -93,35 +93,5 @@ MONKEY = {
}, },
}, },
}, },
"persistent_scanning": {
"title": "Persistent scanning",
"type": "object",
"properties": {
"max_iterations": {
"title": "Max iterations",
"type": "integer",
"default": 1,
"minimum": 1,
"description": "Determines how many iterations of the monkey's full lifecycle "
"should occur "
"(how many times to do the scan)",
},
"timeout_between_iterations": {
"title": "Wait time between iterations",
"type": "integer",
"default": 100,
"minimum": 0,
"description": "Determines for how long (in seconds) should the monkey wait "
"before starting another scan",
},
"retry_failed_explotation": {
"title": "Retry failed exploitation",
"type": "boolean",
"default": True,
"description": "Determines whether the monkey should retry exploiting machines"
" it didn't successfully exploit on previous scans",
},
},
},
}, },
} }

View File

@ -163,11 +163,6 @@
"processlistcollector", "processlistcollector",
"mimikatzcollector" "mimikatzcollector"
] ]
},
"persistent_scanning": {
"max_iterations": 1,
"timeout_between_iterations": 100,
"retry_failed_explotation": true
} }
} }
} }