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 queue
import threading
from copy import deepcopy
from itertools import chain
from queue import Queue
from threading import Event
from typing import Callable, Dict, List, Mapping
@ -36,12 +38,10 @@ class Exploiter:
scan_completed: Event,
stop: Event,
):
# Run vulnerability exploiters before brute force exploiters to minimize the effect of
# account lockout due to invalid credentials
exploiters_to_run = exploiter_config["vulnerability"] + exploiter_config["brute_force"]
exploiters_to_run = self._process_exploiter_config(exploiter_config)
logger.debug(
"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)
@ -49,6 +49,22 @@ class Exploiter:
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(
self,
exploiters_to_run: List[Dict],
@ -83,19 +99,21 @@ class Exploiter:
for exploiter in interruptable_iter(exploiters_to_run, stop):
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)
if exploiter_name != "ZerologonExploiter" and exploiter_results.success:
break
def _run_exploiter(
self, exploiter_name: str, victim_host: VictimHost, stop: Event
self, exploiter_name: str, options: Dict, victim_host: VictimHost, stop: Event
) -> ExploiterResultData:
logger.debug(f"Attempting to use {exploiter_name} on {victim_host}")
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)

View File

@ -602,7 +602,20 @@ class ConfigService:
"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]):
category = (
@ -611,7 +624,7 @@ class ConfigService:
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)

View File

@ -35,12 +35,13 @@ def callback():
@pytest.fixture
def exploiter_config():
return {
"options": {"dropper_path_linux": "/tmp/monkey"},
"brute_force": [
{"name": "PowerShellExploiter"},
{"name": "SSHExploiter"},
{"name": "PowerShellExploiter", "options": {"timeout": 10}},
{"name": "SSHExploiter", "options": {}},
],
"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):
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": [
{"name": "MSSQLExploiter"},
{"name": "PowerShellExploiter"},
{"name": "SSHExploiter"},
{"name": "SmbExploiter"},
{"name": "WmiExploiter"},
{"name": "MSSQLExploiter", "options": {}},
{"name": "PowerShellExploiter", "options": {}},
{"name": "SSHExploiter", "options": {}},
{"name": "SmbExploiter", "options": {}},
{"name": "WmiExploiter", "options": {}},
],
"vulnerability": [
{"name": "DrupalExploiter"},
{"name": "ElasticGroovyExploiter"},
{"name": "HadoopExploiter"},
{"name": "ShellShockExploiter"},
{"name": "Struts2Exploiter"},
{"name": "WebLogicExploiter"},
{"name": "ZerologonExploiter"},
{"name": "DrupalExploiter", "options": {}},
{"name": "ElasticGroovyExploiter", "options": {}},
{"name": "HadoopExploiter", "options": {}},
{"name": "ShellShockExploiter", "options": {}},
{"name": "Struts2Exploiter", "options": {}},
{"name": "WebLogicExploiter", "options": {}},
{"name": "ZerologonExploiter", "options": {}},
],
}
ConfigService.format_flat_config_for_agent(flat_monkey_config)