Merge pull request #464 from guardicore/463/hotfix/exception-on-aws-network-error

463/hotfix/exception on aws network error
This commit is contained in:
Shay Nehmad 2019-10-13 12:34:47 +03:00 committed by GitHub
commit f4b2874698
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 29 deletions

View File

@ -29,14 +29,14 @@ class AwsInstance(object):
AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/instance-id', timeout=2).read() AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/instance-id', timeout=2).read()
self.region = self._parse_region( self.region = self._parse_region(
urllib2.urlopen(AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read()) urllib2.urlopen(AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read())
except urllib2.URLError as e: except (urllib2.URLError, IOError) as e:
logger.debug("Failed init of AwsInstance while getting metadata: {}".format(e.message)) logger.debug("Failed init of AwsInstance while getting metadata: {}".format(e.message), exc_info=True)
try: try:
self.account_id = self._extract_account_id( self.account_id = self._extract_account_id(
urllib2.urlopen( urllib2.urlopen(
AWS_LATEST_METADATA_URI_PREFIX + 'dynamic/instance-identity/document', timeout=2).read()) AWS_LATEST_METADATA_URI_PREFIX + 'dynamic/instance-identity/document', timeout=2).read())
except urllib2.URLError as e: except (urllib2.URLError, IOError) as e:
logger.debug("Failed init of AwsInstance while getting dynamic instance data: {}".format(e.message)) logger.debug("Failed init of AwsInstance while getting dynamic instance data: {}".format(e.message))
@staticmethod @staticmethod

View File

@ -113,7 +113,7 @@ class InfoCollector(object):
:return: None. Updates class information :return: None. Updates class information
""" """
LOG.debug("Reading subnets") LOG.debug("Reading subnets")
self.info['network_info'] =\ self.info['network_info'] = \
{ {
'networks': get_host_subnets(), 'networks': get_host_subnets(),
'netstat': NetstatCollector.get_netstat_info() 'netstat': NetstatCollector.get_netstat_info()
@ -122,28 +122,38 @@ class InfoCollector(object):
def get_azure_info(self): def get_azure_info(self):
""" """
Adds credentials possibly stolen from an Azure VM instance (if we're on one) Adds credentials possibly stolen from an Azure VM instance (if we're on one)
Updates the credentials structure, creating it if neccesary (compat with mimikatz) Updates the credentials structure, creating it if necessary (compat with mimikatz)
:return: None. Updates class information :return: None. Updates class information
""" """
from infection_monkey.config import WormConfiguration # noinspection PyBroadException
if not WormConfiguration.extract_azure_creds: try:
return from infection_monkey.config import WormConfiguration
LOG.debug("Harvesting creds if on an Azure machine") if not WormConfiguration.extract_azure_creds:
azure_collector = AzureCollector() return
if 'credentials' not in self.info: LOG.debug("Harvesting creds if on an Azure machine")
self.info["credentials"] = {} azure_collector = AzureCollector()
azure_creds = azure_collector.extract_stored_credentials() if 'credentials' not in self.info:
for cred in azure_creds: self.info["credentials"] = {}
username = cred[0] azure_creds = azure_collector.extract_stored_credentials()
password = cred[1] for cred in azure_creds:
if username not in self.info["credentials"]: username = cred[0]
self.info["credentials"][username] = {} password = cred[1]
# we might be losing passwords in case of multiple reset attempts on same username if username not in self.info["credentials"]:
# or in case another collector already filled in a password for this user self.info["credentials"][username] = {}
self.info["credentials"][username]['password'] = password # we might be losing passwords in case of multiple reset attempts on same username
if len(azure_creds) != 0: # or in case another collector already filled in a password for this user
self.info["Azure"] = {} self.info["credentials"][username]['password'] = password
self.info["Azure"]['usernames'] = [cred[0] for cred in azure_creds] if len(azure_creds) != 0:
self.info["Azure"] = {}
self.info["Azure"]['usernames'] = [cred[0] for cred in azure_creds]
except Exception:
# If we failed to collect azure info, no reason to fail all the collection. Log and continue.
LOG.error("Failed collecting Azure info.", exc_info=True)
def get_aws_info(self): def get_aws_info(self):
self.info['aws'] = AwsCollector().get_aws_info() # noinspection PyBroadException
try:
self.info['aws'] = AwsCollector().get_aws_info()
except Exception:
# If we failed to collect aws info, no reason to fail all the collection. Log and continue.
LOG.error("Failed collecting AWS info.", exc_info=True)

View File

@ -9,6 +9,7 @@ __author__ = 'itay.mizeretz'
class AwsEnvironment(Environment): class AwsEnvironment(Environment):
def __init__(self): def __init__(self):
super(AwsEnvironment, self).__init__() super(AwsEnvironment, self).__init__()
# Not suppressing error here on purpose. This is critical if we're on AWS env.
self.aws_info = AwsInstance() self.aws_info = AwsInstance()
self._instance_id = self._get_instance_id() self._instance_id = self._get_instance_id()
self.region = self._get_region() self.region = self._get_region()

View File

@ -1,3 +1,5 @@
import logging
from monkey_island.cc.services.config import ConfigService from monkey_island.cc.services.config import ConfigService
from common.cloud.aws_instance import AwsInstance from common.cloud.aws_instance import AwsInstance
from common.cloud.aws_service import AwsService from common.cloud.aws_service import AwsService
@ -7,6 +9,8 @@ from common.cmd.cmd_runner import CmdRunner
__author__ = "itay.mizeretz" __author__ = "itay.mizeretz"
logger = logging.getLogger(__name__)
class RemoteRunAwsService: class RemoteRunAwsService:
aws_instance = None aws_instance = None
@ -23,7 +27,15 @@ class RemoteRunAwsService:
:return: None :return: None
""" """
if RemoteRunAwsService.aws_instance is None: if RemoteRunAwsService.aws_instance is None:
RemoteRunAwsService.try_init_aws_instance()
@staticmethod
def try_init_aws_instance():
# noinspection PyBroadException
try:
RemoteRunAwsService.aws_instance = AwsInstance() RemoteRunAwsService.aws_instance = AwsInstance()
except Exception:
logger.error("Failed init aws instance. Exception info: ", exc_info=True)
@staticmethod @staticmethod
def run_aws_monkeys(instances, island_ip): def run_aws_monkeys(instances, island_ip):
@ -119,7 +131,7 @@ class RemoteRunAwsService:
return r"[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {" \ return r"[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {" \
r"$true}; (New-Object System.Net.WebClient).DownloadFile('https://" + island_ip + \ r"$true}; (New-Object System.Net.WebClient).DownloadFile('https://" + island_ip + \
r":5000/api/monkey/download/monkey-windows-" + bit_text + r".exe','.\\monkey.exe'); " \ r":5000/api/monkey/download/monkey-windows-" + bit_text + r".exe','.\\monkey.exe'); " \
r";Start-Process -FilePath '.\\monkey.exe' -ArgumentList 'm0nk3y -s " + island_ip + r":5000'; " r";Start-Process -FilePath '.\\monkey.exe' -ArgumentList 'm0nk3y -s " + island_ip + r":5000'; "
@staticmethod @staticmethod
def _get_run_monkey_cmd_line(is_linux, is_64bit, island_ip): def _get_run_monkey_cmd_line(is_linux, is_64bit, island_ip):

View File

@ -24,6 +24,7 @@ class AWSExporter(Exporter):
logger.info('No issues were found by the monkey, no need to send anything') logger.info('No issues were found by the monkey, no need to send anything')
return True return True
# Not suppressing error here on purpose.
current_aws_region = AwsInstance().get_region() current_aws_region = AwsInstance().get_region()
for machine in issues_list: for machine in issues_list:
@ -70,6 +71,7 @@ class AWSExporter(Exporter):
configured_product_arn = load_server_configuration_from_file()['aws'].get('sec_hub_product_arn', '') configured_product_arn = load_server_configuration_from_file()['aws'].get('sec_hub_product_arn', '')
product_arn = 'arn:aws:securityhub:{region}:{arn}'.format(region=region, arn=configured_product_arn) product_arn = 'arn:aws:securityhub:{region}:{arn}'.format(region=region, arn=configured_product_arn)
instance_arn = 'arn:aws:ec2:' + str(region) + ':instance:{instance_id}' instance_arn = 'arn:aws:ec2:' + str(region) + ':instance:{instance_id}'
# Not suppressing error here on purpose.
account_id = AwsInstance().get_account_id() account_id = AwsInstance().get_account_id()
logger.debug("aws account id acquired: {}".format(account_id)) logger.debug("aws account id acquired: {}".format(account_id))

View File

@ -9,11 +9,18 @@ logger = logging.getLogger(__name__)
def populate_exporter_list(): def populate_exporter_list():
manager = ReportExporterManager() manager = ReportExporterManager()
RemoteRunAwsService.init() try_add_aws_exporter_to_manager(manager)
if RemoteRunAwsService.is_running_on_aws() and ('aws' == env.get_deployment()):
manager.add_exporter_to_list(AWSExporter)
if len(manager.get_exporters_list()) != 0: if len(manager.get_exporters_list()) != 0:
logger.debug( logger.debug(
"Populated exporters list with the following exporters: {0}".format(str(manager.get_exporters_list()))) "Populated exporters list with the following exporters: {0}".format(str(manager.get_exporters_list())))
def try_add_aws_exporter_to_manager(manager):
# noinspection PyBroadException
try:
RemoteRunAwsService.init()
if RemoteRunAwsService.is_running_on_aws() and ('aws' == env.get_deployment()):
manager.add_exporter_to_list(AWSExporter)
except Exception:
logger.error("Failed adding aws exporter to manager. Exception info:", exc_info=True)