From e0ec62b05770859e09ca1386865c24743796291b Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Tue, 23 Apr 2019 12:02:13 +0300 Subject: [PATCH] Sending finding to AWS security hub without creds --- .../cc/resources/aws_exporter.py | 76 +++++++++---------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/monkey/monkey_island/cc/resources/aws_exporter.py b/monkey/monkey_island/cc/resources/aws_exporter.py index b08c16ae6..b9b85d269 100644 --- a/monkey/monkey_island/cc/resources/aws_exporter.py +++ b/monkey/monkey_island/cc/resources/aws_exporter.py @@ -1,17 +1,17 @@ import logging import uuid from datetime import datetime + import boto3 from botocore.exceptions import UnknownServiceError +from common.cloud.aws_instance import AwsInstance +from monkey_island.cc.environment.environment import load_server_configuration_from_file from monkey_island.cc.resources.exporter import Exporter from monkey_island.cc.services.config import ConfigService -from monkey_island.cc.environment.environment import load_server_configuration_from_file -from common.cloud.aws_instance import AwsInstance __author__ = 'maor.rayzin' - logger = logging.getLogger(__name__) AWS_CRED_CONFIG_KEYS = [['cnc', 'aws_config', 'aws_access_key_id'], @@ -23,18 +23,21 @@ class AWSExporter(Exporter): @staticmethod def handle_report(report_json): - aws = AwsInstance() + findings_list = [] issues_list = report_json['recommendations']['issues'] if not issues_list: logger.info('No issues were found by the monkey, no need to send anything') return True + + current_aws_region = AwsInstance().get_region() + for machine in issues_list: for issue in issues_list[machine]: if issue.get('aws_instance_id', None): - findings_list.append(AWSExporter._prepare_finding(issue, aws.get_region())) + findings_list.append(AWSExporter._prepare_finding(issue, current_aws_region)) - if not AWSExporter._send_findings(findings_list, AWSExporter._get_aws_keys(), aws.get_region()): + if not AWSExporter._send_findings(findings_list, current_aws_region): logger.error('Exporting findings to aws failed') return False @@ -100,17 +103,11 @@ class AWSExporter(Exporter): return AWSExporter.merge_two_dicts(finding, findings_dict[issue['type']](issue, instance_arn)) @staticmethod - def _send_findings(findings_list, creds_dict, region): + def _send_findings(findings_list, region): try: - if not creds_dict: - logger.info('No AWS access credentials received in configuration') - return False - - securityhub = boto3.client('securityhub', - aws_access_key_id=creds_dict.get('aws_access_key_id', ''), - aws_secret_access_key=creds_dict.get('aws_secret_access_key', ''), - region_name=region) - + securityhub = boto3.client('securityhub', region_name=region) + # Assumes the machine has the correct IAM role to do this, @see + # https://github.com/guardicore/monkey/wiki/Monkey-Island:-Running-the-monkey-on-AWS-EC2-instances import_response = securityhub.batch_import_findings(Findings=findings_list) if import_response['ResponseMetadata']['HTTPStatusCode'] == 200: return True @@ -159,7 +156,7 @@ class AWSExporter(Exporter): title="Weak segmentation - Machines were able to communicate over unused ports.", description="Use micro-segmentation policies to disable communication other than the required.", recommendation="Machines are not locked down at port level. Network tunnel was set up from {0} to {1}" - .format(issue['machine'], issue['dest']), + .format(issue['machine'], issue['dest']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -171,9 +168,9 @@ class AWSExporter(Exporter): severity=10, title="Samba servers are vulnerable to 'SambaCry'", description="Change {0} password to a complex one-use password that is not shared with other computers on the network. Update your Samba server to 4.4.14 and up, 4.5.10 and up, or 4.6.4 and up." \ - .format(issue['username']), + .format(issue['username']), recommendation="The machine {0} ({1}) is vulnerable to a SambaCry attack. The Monkey authenticated over the SMB protocol with user {2} and its password, and used the SambaCry vulnerability.".format( - issue['machine'], issue['ip_address'], issue['username']), + issue['machine'], issue['ip_address'], issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -185,9 +182,9 @@ class AWSExporter(Exporter): severity=5, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), + issue['username']), recommendation="The machine {0}({1}) is vulnerable to a SMB attack. The Monkey used a pass-the-hash attack over SMB protocol with user {2}.".format( - issue['machine'], issue['ip_address'], issue['username']), + issue['machine'], issue['ip_address'], issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -199,9 +196,9 @@ class AWSExporter(Exporter): severity=1, title="Machines are accessible using SSH passwords supplied by the user during the Monkey's configuration.", description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), + issue['username']), recommendation="The machine {0} ({1}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH protocol with user {2} and its password.".format( - issue['machine'], issue['ip_address'], issue['username']), + issue['machine'], issue['ip_address'], issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -214,7 +211,7 @@ class AWSExporter(Exporter): title="Machines are accessible using SSH passwords supplied by the user during the Monkey's configuration.", description="Protect {ssh_key} private key with a pass phrase.".format(ssh_key=issue['ssh_key']), recommendation="The machine {machine} ({ip_address}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH protocol with private key {ssh_key}.".format( - machine=issue['machine'], ip_address=issue['ip_address'], ssh_key=issue['ssh_key']), + machine=issue['machine'], ip_address=issue['ip_address'], ssh_key=issue['ssh_key']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -227,7 +224,7 @@ class AWSExporter(Exporter): title="Elastic Search servers are vulnerable to CVE-2015-1427", description="Update your Elastic Search server to version 1.4.3 and up.", recommendation="The machine {0}({1}) is vulnerable to an Elastic Groovy attack. The attack was made possible because the Elastic Search server was not patched against CVE-2015-1427.".format( - issue['machine'], issue['ip_address']), + issue['machine'], issue['ip_address']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -243,7 +240,8 @@ class AWSExporter(Exporter): {0} in the networks {1} \ could directly access the Monkey Island server in the networks {2}.".format(issue['machine'], issue['networks'], - issue['server_networks']), + issue[ + 'server_networks']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -269,7 +267,7 @@ class AWSExporter(Exporter): description="Update your Bash to a ShellShock-patched version.", recommendation="The machine {0} ({1}) is vulnerable to a ShellShock attack. " "The attack was made possible because the HTTP server running on TCP port {2} was vulnerable to a shell injection attack on the paths: {3}.".format( - issue['machine'], issue['ip_address'], issue['port'], issue['paths']), + issue['machine'], issue['ip_address'], issue['port'], issue['paths']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -281,9 +279,9 @@ class AWSExporter(Exporter): severity=1, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), + issue['username']), recommendation="The machine {0} ({1}) is vulnerable to a SMB attack. The Monkey authenticated over the SMB protocol with user {2} and its password.".format( - issue['machine'], issue['ip_address'], issue['username']), + issue['machine'], issue['ip_address'], issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -296,7 +294,7 @@ class AWSExporter(Exporter): title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.", recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey authenticated over the WMI protocol with user {username} and its password.".format( - machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), + machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -308,9 +306,9 @@ class AWSExporter(Exporter): severity=1, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), + issue['username']), recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey used a pass-the-hash attack over WMI protocol with user {username}".format( - machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), + machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -322,9 +320,9 @@ class AWSExporter(Exporter): severity=1, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), + issue['username']), recommendation="The machine machine ({ip_address}) is vulnerable to a RDP attack. The Monkey authenticated over the RDP protocol with user {username} and its password.".format( - machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), + machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -337,7 +335,7 @@ class AWSExporter(Exporter): title="Multiple users have the same password.", description="Some domain users are sharing passwords, this should be fixed by changing passwords.", recommendation="These users are sharing access password: {shared_with}.".format( - shared_with=issue['shared_with']), + shared_with=issue['shared_with']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -350,7 +348,7 @@ class AWSExporter(Exporter): title="Shared local administrator account - Different machines have the same account as a local administrator.", description="Make sure the right administrator accounts are managing the right machines, and that there isn\'t an unintentional local admin sharing.", recommendation="Here is a list of machines which the account {username} is defined as an administrator: {shared_machines}".format( - username=issue['username'], shared_machines=issue['shared_machines']), + username=issue['username'], shared_machines=issue['shared_machines']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -363,7 +361,7 @@ class AWSExporter(Exporter): title="Mimikatz found login credentials of a user who has admin access to a server defined as critical.", description="This critical machine is open to attacks via strong users with access to it.", recommendation="The services: {services} have been found on the machine thus classifying it as a critical machine. These users has access to it:{threatening_users}.".format( - services=issue['services'], threatening_users=issue['threatening_users']), + services=issue['services'], threatening_users=issue['threatening_users']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -377,7 +375,7 @@ class AWSExporter(Exporter): description="Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions.", recommendation="Struts2 server at {machine} ({ip_address}) is vulnerable to remote code execution attack." " The attack was made possible because the server is using an old version of Jakarta based file upload Multipart parser.".format( - machine=issue['machine'], ip_address=issue['ip_address']), + machine=issue['machine'], ip_address=issue['ip_address']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -392,7 +390,7 @@ class AWSExporter(Exporter): "Vulnerable versions are 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0.", recommendation="Oracle WebLogic server at {machine} ({ip_address}) is vulnerable to remote code execution attack." " The attack was made possible due to incorrect permission assignment in Oracle Fusion Middleware (subcomponent: WLS Security).".format( - machine=issue['machine'], ip_address=issue['ip_address']), + machine=issue['machine'], ip_address=issue['ip_address']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None )