forked from p15670423/monkey
Merge pull request #2297 from guardicore/2182-remove-credentialstelem
Remove CredentialsTelem
This commit is contained in:
commit
4884313cba
|
@ -1,7 +1,7 @@
|
|||
from pprint import pformat
|
||||
from typing import List
|
||||
|
||||
from common.credentials import CredentialComponentType, Credentials
|
||||
from common.credentials import Credentials, LMHash, NTHash, Username
|
||||
from envs.monkey_zoo.blackbox.analyzers.analyzer import Analyzer
|
||||
from envs.monkey_zoo.blackbox.analyzers.analyzer_log import AnalyzerLog
|
||||
from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient
|
||||
|
@ -36,11 +36,11 @@ class ZerologonAnalyzer(Analyzer):
|
|||
credentials_on_island = set()
|
||||
|
||||
for credentials in propagation_credentials:
|
||||
if credentials.identity.credential_type is CredentialComponentType.USERNAME:
|
||||
if isinstance(credentials.identity, Username):
|
||||
credentials_on_island.update([credentials.identity.username])
|
||||
if credentials.secret.credential_type is CredentialComponentType.NT_HASH:
|
||||
if isinstance(credentials.secret, NTHash):
|
||||
credentials_on_island.update([credentials.secret.nt_hash])
|
||||
if credentials.secret.credential_type is CredentialComponentType.LM_HASH:
|
||||
if isinstance(credentials.secret, LMHash):
|
||||
credentials_on_island.update([credentials.secret.lm_hash])
|
||||
|
||||
return list(credentials_on_island)
|
||||
|
|
|
@ -87,9 +87,9 @@ test_agent_configuration = _add_credential_collectors(test_agent_configuration)
|
|||
test_agent_configuration = _add_http_ports(test_agent_configuration)
|
||||
|
||||
CREDENTIALS = (
|
||||
Credentials(Username("m0nk3y"), None),
|
||||
Credentials(None, Password("Ivrrw5zEzs")),
|
||||
Credentials(None, Password("Xk8VDTsC")),
|
||||
Credentials(identity=Username(username="m0nk3y"), secret=None),
|
||||
Credentials(identity=None, secret=Password(password="Ivrrw5zEzs")),
|
||||
Credentials(identity=None, secret=Password(password="Xk8VDTsC")),
|
||||
)
|
||||
|
||||
depth_1_a_test_configuration = dataclasses.replace(noop_test_configuration)
|
||||
|
|
|
@ -42,8 +42,8 @@ test_agent_configuration = _add_subnets(test_agent_configuration)
|
|||
test_agent_configuration = _add_tcp_ports(test_agent_configuration)
|
||||
|
||||
CREDENTIALS = (
|
||||
Credentials(Username("m0nk3y"), None),
|
||||
Credentials(None, Password("^NgDvY59~8")),
|
||||
Credentials(identity=Username(username="m0nk3y"), secret=None),
|
||||
Credentials(identity=None, secret=Password(password="^NgDvY59~8")),
|
||||
)
|
||||
|
||||
depth_2_a_test_configuration = dataclasses.replace(noop_test_configuration)
|
||||
|
|
|
@ -56,14 +56,14 @@ test_agent_configuration = _add_subnets(test_agent_configuration)
|
|||
test_agent_configuration = _add_tcp_ports(test_agent_configuration)
|
||||
|
||||
CREDENTIALS = (
|
||||
Credentials(Username("m0nk3y"), None),
|
||||
Credentials(Username("m0nk3y-user"), None),
|
||||
Credentials(None, Password("Passw0rd!")),
|
||||
Credentials(None, Password("3Q=(Ge(+&w]*")),
|
||||
Credentials(None, Password("`))jU7L(w}")),
|
||||
Credentials(None, NTHash("d0f0132b308a0c4e5d1029cc06f48692")),
|
||||
Credentials(None, NTHash("5da0889ea2081aa79f6852294cba4a5e")),
|
||||
Credentials(None, NTHash("50c9987a6bf1ac59398df9f911122c9b")),
|
||||
Credentials(identity=Username(username="m0nk3y"), secret=None),
|
||||
Credentials(identity=Username(username="m0nk3y-user"), secret=None),
|
||||
Credentials(identity=None, secret=Password(password="Passw0rd!")),
|
||||
Credentials(identity=None, secret=Password(password="3Q=(Ge(+&w]*")),
|
||||
Credentials(identity=None, secret=Password(password="`))jU7L(w}")),
|
||||
Credentials(identity=None, secret=NTHash(nt_hash="d0f0132b308a0c4e5d1029cc06f48692")),
|
||||
Credentials(identity=None, secret=NTHash(nt_hash="5da0889ea2081aa79f6852294cba4a5e")),
|
||||
Credentials(identity=None, secret=NTHash(nt_hash="50c9987a6bf1ac59398df9f911122c9b")),
|
||||
)
|
||||
|
||||
depth_3_a_test_configuration = dataclasses.replace(noop_test_configuration)
|
||||
|
|
|
@ -49,11 +49,11 @@ test_agent_configuration = _add_subnets(test_agent_configuration)
|
|||
test_agent_configuration = _add_tcp_ports(test_agent_configuration)
|
||||
|
||||
CREDENTIALS = (
|
||||
Credentials(Username("m0nk3y"), None),
|
||||
Credentials(None, Password("3Q=(Ge(+&w]*")),
|
||||
Credentials(None, Password("`))jU7L(w}")),
|
||||
Credentials(None, Password("prM2qsroTI")),
|
||||
Credentials(None, Password("t67TC5ZDmz")),
|
||||
Credentials(identity=Username(username="m0nk3y"), secret=None),
|
||||
Credentials(identity=None, secret=Password(password="3Q=(Ge(+&w]*")),
|
||||
Credentials(identity=None, secret=Password(password="`))jU7L(w}")),
|
||||
Credentials(identity=None, secret=Password(password="prM2qsroTI")),
|
||||
Credentials(identity=None, secret=Password(password="t67TC5ZDmz")),
|
||||
)
|
||||
|
||||
depth_4_a_test_configuration = dataclasses.replace(noop_test_configuration)
|
||||
|
|
|
@ -42,14 +42,14 @@ test_agent_configuration = _add_subnets(test_agent_configuration)
|
|||
test_agent_configuration = _add_tcp_ports(test_agent_configuration)
|
||||
|
||||
CREDENTIALS = (
|
||||
Credentials(Username("Administrator"), None),
|
||||
Credentials(Username("m0nk3y"), None),
|
||||
Credentials(Username("user"), None),
|
||||
Credentials(None, Password("Ivrrw5zEzs")),
|
||||
Credentials(None, Password("Password1!")),
|
||||
Credentials(None, NTHash("d0f0132b308a0c4e5d1029cc06f48692")),
|
||||
Credentials(None, NTHash("5da0889ea2081aa79f6852294cba4a5e")),
|
||||
Credentials(None, NTHash("50c9987a6bf1ac59398df9f911122c9b")),
|
||||
Credentials(identity=Username(username="Administrator"), secret=None),
|
||||
Credentials(identity=Username(username="m0nk3y"), secret=None),
|
||||
Credentials(identity=Username(username="user"), secret=None),
|
||||
Credentials(identity=None, secret=Password(password="Ivrrw5zEzs")),
|
||||
Credentials(identity=None, secret=Password(password="Password1!")),
|
||||
Credentials(identity=None, secret=NTHash(nt_hash="d0f0132b308a0c4e5d1029cc06f48692")),
|
||||
Credentials(identity=None, secret=NTHash(nt_hash="5da0889ea2081aa79f6852294cba4a5e")),
|
||||
Credentials(identity=None, secret=NTHash(nt_hash="50c9987a6bf1ac59398df9f911122c9b")),
|
||||
)
|
||||
|
||||
smb_pth_test_configuration = dataclasses.replace(noop_test_configuration)
|
||||
|
|
|
@ -50,11 +50,11 @@ test_agent_configuration = _add_tcp_ports(test_agent_configuration)
|
|||
test_agent_configuration = _add_credential_collectors(test_agent_configuration)
|
||||
|
||||
CREDENTIALS = (
|
||||
Credentials(Username("Administrator"), None),
|
||||
Credentials(Username("m0nk3y"), None),
|
||||
Credentials(Username("user"), None),
|
||||
Credentials(None, Password("Ivrrw5zEzs")),
|
||||
Credentials(None, Password("Password1!")),
|
||||
Credentials(identity=Username(username="Administrator"), secret=None),
|
||||
Credentials(identity=Username(username="m0nk3y"), secret=None),
|
||||
Credentials(identity=Username(username="user"), secret=None),
|
||||
Credentials(identity=None, secret=Password(password="Ivrrw5zEzs")),
|
||||
Credentials(identity=None, secret=Password(password="Password1!")),
|
||||
)
|
||||
|
||||
wmi_mimikatz_test_configuration = dataclasses.replace(noop_test_configuration)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
class TelemCategoryEnum:
|
||||
ATTACK = "attack"
|
||||
AWS_INFO = "aws_info"
|
||||
CREDENTIALS = "credentials"
|
||||
EXPLOIT = "exploit"
|
||||
FILE_ENCRYPTION = "file_encryption"
|
||||
POST_BREACH = "post_breach"
|
||||
|
|
|
@ -25,7 +25,6 @@ from infection_monkey.exploit.zerologon_utils.options import OptionsForSecretsdu
|
|||
from infection_monkey.exploit.zerologon_utils.vuln_assessment import get_dc_details, is_exploitable
|
||||
from infection_monkey.exploit.zerologon_utils.wmiexec import Wmiexec
|
||||
from infection_monkey.i_puppet import ExploiterResultData
|
||||
from infection_monkey.telemetry.credentials_telem import CredentialsTelem
|
||||
from infection_monkey.utils.capture_output import StdoutCapture
|
||||
from infection_monkey.utils.threading import interruptible_iter
|
||||
|
||||
|
@ -133,6 +132,8 @@ class ZerologonExploiter(HostExploiter):
|
|||
except BaseException as e:
|
||||
logger.info(f"Unexpected error: {e}")
|
||||
|
||||
return None
|
||||
|
||||
def attempt_exploit(self, rpc_con: rpcrt.DCERPC_v5) -> object:
|
||||
request = nrpc.NetrServerPasswordSet2()
|
||||
ZerologonExploiter._set_up_request(request, self.dc_name)
|
||||
|
@ -221,9 +222,9 @@ class ZerologonExploiter(HostExploiter):
|
|||
|
||||
finally:
|
||||
if rpc_con:
|
||||
rpc_con.disconnect()
|
||||
rpc_con.disconnect() # type: ignore[attr-defined]
|
||||
|
||||
def get_all_user_creds(self) -> List[Tuple[str, Dict]]:
|
||||
def get_all_user_creds(self) -> Optional[List[Tuple[str, Dict]]]:
|
||||
try:
|
||||
options = OptionsForSecretsdump(
|
||||
# format for DC account - "NetBIOSName$@0.0.0.0"
|
||||
|
@ -238,7 +239,7 @@ class ZerologonExploiter(HostExploiter):
|
|||
|
||||
self._extract_user_creds_from_secrets(dumped_secrets=dumped_secrets)
|
||||
|
||||
creds_to_use_for_getting_original_pwd_hashes = []
|
||||
creds_to_use_for_getting_original_pwd_hashes: List[Tuple[str, Dict]] = []
|
||||
admin = "Administrator"
|
||||
for user in self._extracted_creds.keys():
|
||||
if user == admin: # most likely to work so try this first
|
||||
|
@ -303,19 +304,20 @@ class ZerologonExploiter(HostExploiter):
|
|||
Credentials(identity=Username(username=user), secret=NTHash(nt_hash=nthash)),
|
||||
]
|
||||
|
||||
self.telemetry_messenger.send_telemetry(CredentialsTelem(extracted_credentials))
|
||||
self._publish_credentials_stolen_event(extracted_credentials)
|
||||
|
||||
def _publish_credentials_stolen_event(self, extracted_credentials: Sequence[Credentials]):
|
||||
def _publish_credentials_stolen_event(
|
||||
self, extracted_credentials: Sequence[Credentials]
|
||||
) -> None:
|
||||
credentials_stolen_event = CredentialsStolenEvent(
|
||||
tags=ZEROLOGON_EVENT_TAGS,
|
||||
stolen_credentials=extracted_credentials,
|
||||
)
|
||||
self.event_queue.publish(credentials_stolen_event)
|
||||
|
||||
def get_original_pwd_nthash(self, username: str, user_pwd_hashes: List[str]) -> str:
|
||||
def get_original_pwd_nthash(self, username: str, user_pwd_hashes: List[str]) -> Optional[str]:
|
||||
if not self.save_HKLM_keys_locally(username, user_pwd_hashes):
|
||||
return
|
||||
return None
|
||||
|
||||
try:
|
||||
options = OptionsForSecretsdump(
|
||||
|
@ -341,6 +343,8 @@ class ZerologonExploiter(HostExploiter):
|
|||
finally:
|
||||
self.remove_locally_saved_HKLM_keys()
|
||||
|
||||
return None
|
||||
|
||||
def save_HKLM_keys_locally(self, username: str, user_pwd_hashes: List[str]) -> bool:
|
||||
logger.info(f"Starting remote shell on victim with user: {username}")
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ from infection_monkey.i_control_channel import IControlChannel, IslandCommunicat
|
|||
from infection_monkey.i_master import IMaster
|
||||
from infection_monkey.i_puppet import IPuppet
|
||||
from infection_monkey.model import VictimHostFactory
|
||||
from infection_monkey.telemetry.credentials_telem import CredentialsTelem
|
||||
from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger
|
||||
from infection_monkey.telemetry.post_breach_telem import PostBreachTelem
|
||||
from infection_monkey.utils.propagation import maximum_depth_reached
|
||||
|
@ -194,9 +193,7 @@ class AutomatedMaster(IMaster):
|
|||
def _collect_credentials(self, collector: PluginConfiguration):
|
||||
credentials = self._puppet.run_credential_collector(collector.name, collector.options)
|
||||
|
||||
if credentials:
|
||||
self._telemetry_messenger.send_telemetry(CredentialsTelem(credentials))
|
||||
else:
|
||||
if not credentials:
|
||||
logger.debug(f"No credentials were collected by {collector}")
|
||||
|
||||
def _run_pba(self, pba: PluginConfiguration):
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
from typing import Iterable
|
||||
|
||||
from common.common_consts.telem_categories import TelemCategoryEnum
|
||||
from common.credentials import Credentials
|
||||
from infection_monkey.telemetry.base_telem import BaseTelem
|
||||
|
||||
|
||||
class CredentialsTelem(BaseTelem):
|
||||
telem_category = TelemCategoryEnum.CREDENTIALS
|
||||
|
||||
def __init__(self, credentials: Iterable[Credentials]):
|
||||
"""
|
||||
Used to send information about stolen or discovered credentials to the Island.
|
||||
:param credentials: An iterable containing credentials to be sent to the Island.
|
||||
"""
|
||||
self._credentials = credentials
|
||||
|
||||
@property
|
||||
def credentials(self) -> Iterable[Credentials]:
|
||||
return iter(self._credentials)
|
||||
|
||||
def send(self, log_data=True):
|
||||
super().send(log_data=False)
|
||||
|
||||
def get_data(self):
|
||||
return [c.dict(simplify=True) for c in self._credentials]
|
|
@ -85,10 +85,6 @@ class TelemetryFeed(AbstractResource):
|
|||
def get_scan_telem_brief(telem):
|
||||
return "Monkey discovered machine %s." % telem["data"]["machine"]["ip_addr"]
|
||||
|
||||
@staticmethod
|
||||
def get_credentials_telem_brief(_):
|
||||
return "Monkey collected stole some credentials."
|
||||
|
||||
@staticmethod
|
||||
def get_trace_telem_brief(telem):
|
||||
return "Trace: %s" % telem["data"]["msg"]
|
||||
|
@ -116,7 +112,6 @@ class TelemetryFeed(AbstractResource):
|
|||
|
||||
|
||||
TELEM_PROCESS_DICT = {
|
||||
TelemCategoryEnum.CREDENTIALS: TelemetryFeed.get_credentials_telem_brief,
|
||||
TelemCategoryEnum.EXPLOIT: TelemetryFeed.get_exploit_telem_brief,
|
||||
TelemCategoryEnum.POST_BREACH: TelemetryFeed.get_post_breach_telem_brief,
|
||||
TelemCategoryEnum.SCAN: TelemetryFeed.get_scan_telem_brief,
|
||||
|
|
|
@ -11,7 +11,6 @@ from common.agent_configuration import (
|
|||
AgentConfiguration,
|
||||
)
|
||||
from common.aws import AWSInstance
|
||||
from common.common_consts.telem_categories import TelemCategoryEnum
|
||||
from common.event_queue import IAgentEventQueue, PyPubSubAgentEventQueue
|
||||
from common.utils.file_utils import get_binary_io_sha256_hash
|
||||
from monkey_island.cc.event_queue import IIslandEventQueue, PyPubSubIslandEventQueue
|
||||
|
@ -40,12 +39,6 @@ from monkey_island.cc.server_utils.encryption import ILockableEncryptor, Reposit
|
|||
from monkey_island.cc.services import AWSService, IslandModeService
|
||||
from monkey_island.cc.services.attack.technique_reports.T1003 import T1003, T1003GetReportData
|
||||
from monkey_island.cc.services.run_local_monkey import LocalMonkeyRunService
|
||||
from monkey_island.cc.services.telemetry.processing.credentials.credentials_parser import (
|
||||
CredentialsParser,
|
||||
)
|
||||
from monkey_island.cc.services.telemetry.processing.processing import (
|
||||
TELEMETRY_CATEGORY_TO_PROCESSING_FUNC,
|
||||
)
|
||||
from monkey_island.cc.setup.mongo.mongo_setup import MONGO_URL
|
||||
|
||||
from . import AuthenticationService
|
||||
|
@ -165,9 +158,3 @@ def _dirty_hacks(container: DIContainer):
|
|||
# Patches attack technique T1003 which is a static class
|
||||
# but it needs stolen credentials from the database
|
||||
T1003.get_report_data = container.resolve(T1003GetReportData)
|
||||
|
||||
# Note: A hack to resolve credentials parser
|
||||
# It changes telemetry processing function, this will be refactored!
|
||||
TELEMETRY_CATEGORY_TO_PROCESSING_FUNC[TelemCategoryEnum.CREDENTIALS] = container.resolve(
|
||||
CredentialsParser
|
||||
)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import logging
|
||||
from typing import Mapping
|
||||
|
||||
from common.credentials import Credentials
|
||||
from monkey_island.cc.repository import ICredentialsRepository
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CredentialsParser:
|
||||
"""
|
||||
This class parses and stores telemetry credentials.
|
||||
"""
|
||||
|
||||
def __init__(self, credentials_repository: ICredentialsRepository):
|
||||
self._credentials_repository = credentials_repository
|
||||
|
||||
def __call__(self, telemetry_dict, _agent_configuration):
|
||||
self._parse_credentials(telemetry_dict, _agent_configuration)
|
||||
|
||||
def _parse_credentials(self, telemetry_dict: Mapping, _agent_configuration):
|
||||
credentials = [Credentials(**credential) for credential in telemetry_dict["data"]]
|
||||
|
||||
self._credentials_repository.save_stolen_credentials(credentials)
|
|
@ -15,7 +15,6 @@ TELEMETRY_CATEGORY_TO_PROCESSING_FUNC = {
|
|||
# `lambda *args, **kwargs: None` is a no-op.
|
||||
TelemCategoryEnum.ATTACK: lambda *args, **kwargs: None,
|
||||
TelemCategoryEnum.AWS_INFO: process_aws_telemetry,
|
||||
TelemCategoryEnum.CREDENTIALS: None, # this is set in monkey_island/cc/services/initialize.py
|
||||
TelemCategoryEnum.EXPLOIT: process_exploit_telemetry,
|
||||
TelemCategoryEnum.POST_BREACH: process_post_breach_telemetry,
|
||||
TelemCategoryEnum.SCAN: process_scan_telemetry,
|
||||
|
@ -23,10 +22,6 @@ TELEMETRY_CATEGORY_TO_PROCESSING_FUNC = {
|
|||
TelemCategoryEnum.TRACE: lambda *args, **kwargs: None,
|
||||
}
|
||||
|
||||
# Don't save credential telemetries in telemetries collection.
|
||||
# Credentials are stored in StolenCredentials documents
|
||||
UNSAVED_TELEMETRIES = [TelemCategoryEnum.CREDENTIALS]
|
||||
|
||||
|
||||
def process_telemetry(telemetry_json, agent_configuration: AgentConfiguration):
|
||||
try:
|
||||
|
@ -38,8 +33,7 @@ def process_telemetry(telemetry_json, agent_configuration: AgentConfiguration):
|
|||
else:
|
||||
logger.info("Got unknown type of telemetry: %s" % telem_category)
|
||||
|
||||
if telem_category not in UNSAVED_TELEMETRIES:
|
||||
save_telemetry(telemetry_json)
|
||||
save_telemetry(telemetry_json)
|
||||
|
||||
except Exception as ex:
|
||||
logger.error(
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from common.credentials import Credentials, Password, Username
|
||||
from infection_monkey.telemetry.credentials_telem import CredentialsTelem
|
||||
|
||||
USERNAME = "m0nkey"
|
||||
PASSWORD = "mmm"
|
||||
PUBLIC_KEY = "pub_key"
|
||||
PRIVATE_KEY = "priv_key"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def credentials_for_test():
|
||||
return Credentials(identity=Username(username=USERNAME), secret=Password(password=PASSWORD))
|
||||
|
||||
|
||||
def test_credential_telem_send(spy_send_telemetry, credentials_for_test):
|
||||
|
||||
expected_data = [credentials_for_test.dict(simplify=True)]
|
||||
|
||||
telem = CredentialsTelem([credentials_for_test])
|
||||
telem.send()
|
||||
|
||||
assert json.loads(spy_send_telemetry.data) == expected_data
|
||||
assert spy_send_telemetry.telem_category == "credentials"
|
||||
|
||||
|
||||
def test_credentials_property(credentials_for_test):
|
||||
telem = CredentialsTelem([credentials_for_test])
|
||||
|
||||
assert len(list(telem.credentials)) == 1
|
||||
assert list(telem.credentials)[0] == credentials_for_test
|
Loading…
Reference in New Issue