Agent: Add telemetry type for sending stolen credentials

This commit is contained in:
Mike Salvatore 2022-02-16 11:41:22 -05:00
parent 49f1675b38
commit 040b37697b
3 changed files with 78 additions and 0 deletions

View File

@ -9,3 +9,4 @@ class TelemCategoryEnum:
ATTACK = "attack"
FILE_ENCRYPTION = "file_encryption"
AWS_INFO = "aws_info"
CREDENTIALS = "credentials"

View File

@ -0,0 +1,40 @@
import enum
import json
from typing import Dict, Iterable
from common.common_consts.telem_categories import TelemCategoryEnum
from infection_monkey.i_puppet.credential_collection import Credentials, ICredentialComponent
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
def get_data(self) -> Dict:
# TODO: At a later time we can consider factoring this into a Serializer class or similar.
return json.loads(json.dumps(self._credentials, default=_serialize))
def _serialize(obj):
if isinstance(obj, enum.Enum):
return obj.name
if isinstance(obj, ICredentialComponent):
# This is a workaround for ICredentialComponents that are implemented as dataclasses. If the
# credential_type attribute is populated with `field(init=False, ...)`, then credential_type
# is not added to the object's __dict__ attribute. The biggest risk of this workaround is
# that we might change the name of the credential_type field in ICredentialComponents, but
# automated refactoring tools would not detect that this string needs to change. This is
# mittigated by the call to getattr() below, which will raise an AttributeException if the
# attribute name changes and a unit test will fail under these conditions.
credential_type = getattr(obj, "credential_type")
return dict(obj.__dict__, **{"credential_type": credential_type})
return getattr(obj, "__dict__", str(obj))

View File

@ -0,0 +1,37 @@
import json
from infection_monkey.credential_collectors import Password, SSHKeypair, Username
from infection_monkey.i_puppet import Credentials
from infection_monkey.telemetry.credentials_telem import CredentialsTelem
def test_credential_telem_send(spy_send_telemetry):
username = "m0nkey"
password = "mmm"
public_key = "pub_key"
private_key = "priv_key"
expected_data = [
{
"identities": [{"username": username, "credential_type": "USERNAME"}],
"secrets": [
{"password": password, "credential_type": "PASSWORD"},
{
"private_key": "pub_key",
"public_key": "priv_key",
"credential_type": "SSH_KEYPAIR",
},
],
}
]
credentials = Credentials(
[Username(username)], [Password(password), SSHKeypair(public_key, private_key)]
)
telem = CredentialsTelem([credentials])
telem.send()
expected_data = json.dumps(expected_data, cls=telem.json_encoder)
assert spy_send_telemetry.data == expected_data
assert spy_send_telemetry.telem_category == "credentials"