Merge pull request #2297 from guardicore/2182-remove-credentialstelem

Remove CredentialsTelem
This commit is contained in:
Mike Salvatore 2022-09-15 07:42:37 -04:00 committed by GitHub
commit 4884313cba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 49 additions and 157 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -1,7 +1,6 @@
class TelemCategoryEnum:
ATTACK = "attack"
AWS_INFO = "aws_info"
CREDENTIALS = "credentials"
EXPLOIT = "exploit"
FILE_ENCRYPTION = "file_encryption"
POST_BREACH = "post_breach"

View File

@ -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}")

View File

@ -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):

View File

@ -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]

View File

@ -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,

View File

@ -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
)

View File

@ -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)

View File

@ -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(

View File

@ -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