Merge pull request #1724 from guardicore/1605-pass-wormconfig-options

1605 pass wormconfig options
This commit is contained in:
ilija-lazoroski 2022-02-21 13:52:28 +01:00 committed by GitHub
commit 4b83c79134
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 24 deletions

View File

@ -1,6 +1,8 @@
import logging import logging
import queue import queue
import threading import threading
from copy import deepcopy
from itertools import chain
from queue import Queue from queue import Queue
from threading import Event from threading import Event
from typing import Callable, Dict, List, Mapping from typing import Callable, Dict, List, Mapping
@ -36,12 +38,10 @@ class Exploiter:
scan_completed: Event, scan_completed: Event,
stop: Event, stop: Event,
): ):
# Run vulnerability exploiters before brute force exploiters to minimize the effect of exploiters_to_run = self._process_exploiter_config(exploiter_config)
# account lockout due to invalid credentials
exploiters_to_run = exploiter_config["vulnerability"] + exploiter_config["brute_force"]
logger.debug( logger.debug(
"Agent is configured to run the following exploiters in order: " "Agent is configured to run the following exploiters in order: "
f"{','.join([e['name'] for e in exploiters_to_run])}" f"{', '.join([e['name'] for e in exploiters_to_run])}"
) )
exploit_args = (exploiters_to_run, hosts_to_exploit, results_callback, scan_completed, stop) exploit_args = (exploiters_to_run, hosts_to_exploit, results_callback, scan_completed, stop)
@ -49,6 +49,22 @@ class Exploiter:
target=self._exploit_hosts_on_queue, args=exploit_args, num_workers=self._num_workers target=self._exploit_hosts_on_queue, args=exploit_args, num_workers=self._num_workers
) )
@staticmethod
def _process_exploiter_config(exploiter_config: Mapping) -> List[Mapping]:
# Run vulnerability exploiters before brute force exploiters to minimize the effect of
# account lockout due to invalid credentials
ordered_exploiters = chain(
exploiter_config["vulnerability"], exploiter_config["brute_force"]
)
exploiters_to_run = list(deepcopy(ordered_exploiters))
for exploiter in exploiters_to_run:
# This order allows exploiter-specific options to
# override general options for all exploiters.
exploiter["options"] = {**exploiter_config["options"], **exploiter["options"]}
return exploiters_to_run
def _exploit_hosts_on_queue( def _exploit_hosts_on_queue(
self, self,
exploiters_to_run: List[Dict], exploiters_to_run: List[Dict],
@ -83,19 +99,21 @@ class Exploiter:
for exploiter in interruptable_iter(exploiters_to_run, stop): for exploiter in interruptable_iter(exploiters_to_run, stop):
exploiter_name = exploiter["name"] exploiter_name = exploiter["name"]
exploiter_results = self._run_exploiter(exploiter_name, victim_host, stop) exploiter_results = self._run_exploiter(
exploiter_name, exploiter["options"], victim_host, stop
)
results_callback(exploiter_name, victim_host, exploiter_results) results_callback(exploiter_name, victim_host, exploiter_results)
if exploiter_name != "ZerologonExploiter" and exploiter_results.success: if exploiter_name != "ZerologonExploiter" and exploiter_results.success:
break break
def _run_exploiter( def _run_exploiter(
self, exploiter_name: str, victim_host: VictimHost, stop: Event self, exploiter_name: str, options: Dict, victim_host: VictimHost, stop: Event
) -> ExploiterResultData: ) -> ExploiterResultData:
logger.debug(f"Attempting to use {exploiter_name} on {victim_host}") logger.debug(f"Attempting to use {exploiter_name} on {victim_host}")
credentials = self._get_credentials_for_propagation() credentials = self._get_credentials_for_propagation()
options = {"credentials": credentials} options = {"credentials": credentials, **options}
return self._puppet.exploit_host(exploiter_name, victim_host.ip_addr, options, stop) return self._puppet.exploit_host(exploiter_name, victim_host.ip_addr, options, stop)

View File

@ -602,7 +602,20 @@ class ConfigService:
"WmiExploiter", "WmiExploiter",
} }
formatted_exploiters_config = {"brute_force": [], "vulnerability": []} exploit_options = {}
for dropper_target in [
"dropper_target_path_linux",
"dropper_target_path_win_32",
"dropper_target_path_win_64",
]:
exploit_options[dropper_target] = config.get(dropper_target, "")
formatted_exploiters_config = {
"options": exploit_options,
"brute_force": [],
"vulnerability": [],
}
for exploiter in sorted(config[flat_config_exploiter_classes_field]): for exploiter in sorted(config[flat_config_exploiter_classes_field]):
category = ( category = (
@ -611,7 +624,7 @@ class ConfigService:
else vulnerability_category else vulnerability_category
) )
formatted_exploiters_config[category].append({"name": exploiter}) formatted_exploiters_config[category].append({"name": exploiter, "options": {}})
config.pop(flat_config_exploiter_classes_field, None) config.pop(flat_config_exploiter_classes_field, None)

View File

@ -35,12 +35,13 @@ def callback():
@pytest.fixture @pytest.fixture
def exploiter_config(): def exploiter_config():
return { return {
"options": {"dropper_path_linux": "/tmp/monkey"},
"brute_force": [ "brute_force": [
{"name": "PowerShellExploiter"}, {"name": "PowerShellExploiter", "options": {"timeout": 10}},
{"name": "SSHExploiter"}, {"name": "SSHExploiter", "options": {}},
], ],
"vulnerability": [ "vulnerability": [
{"name": "ZerologonExploiter"}, {"name": "ZerologonExploiter", "options": {}},
], ],
} }

View File

@ -171,21 +171,26 @@ def test_format_config_for_agent__network_scan(flat_monkey_config):
def test_format_config_for_agent__exploiters(flat_monkey_config): def test_format_config_for_agent__exploiters(flat_monkey_config):
expected_exploiters_config = { expected_exploiters_config = {
"options": {
"dropper_target_path_linux": "/tmp/monkey",
"dropper_target_path_win_32": r"C:\Windows\temp\monkey32.exe",
"dropper_target_path_win_64": r"C:\Windows\temp\monkey64.exe",
},
"brute_force": [ "brute_force": [
{"name": "MSSQLExploiter"}, {"name": "MSSQLExploiter", "options": {}},
{"name": "PowerShellExploiter"}, {"name": "PowerShellExploiter", "options": {}},
{"name": "SSHExploiter"}, {"name": "SSHExploiter", "options": {}},
{"name": "SmbExploiter"}, {"name": "SmbExploiter", "options": {}},
{"name": "WmiExploiter"}, {"name": "WmiExploiter", "options": {}},
], ],
"vulnerability": [ "vulnerability": [
{"name": "DrupalExploiter"}, {"name": "DrupalExploiter", "options": {}},
{"name": "ElasticGroovyExploiter"}, {"name": "ElasticGroovyExploiter", "options": {}},
{"name": "HadoopExploiter"}, {"name": "HadoopExploiter", "options": {}},
{"name": "ShellShockExploiter"}, {"name": "ShellShockExploiter", "options": {}},
{"name": "Struts2Exploiter"}, {"name": "Struts2Exploiter", "options": {}},
{"name": "WebLogicExploiter"}, {"name": "WebLogicExploiter", "options": {}},
{"name": "ZerologonExploiter"}, {"name": "ZerologonExploiter", "options": {}},
], ],
} }
ConfigService.format_flat_config_for_agent(flat_monkey_config) ConfigService.format_flat_config_for_agent(flat_monkey_config)