Skip to content

Commit

Permalink
Merge pull request #696 from nccgroup/develop
Browse files Browse the repository at this point in the history
release/5.9.0
  • Loading branch information
x4v13r64 committed Jul 2, 2020
2 parents bc0ef14 + 5c21294 commit 8291714
Show file tree
Hide file tree
Showing 360 changed files with 21,411 additions and 9,149 deletions.
7 changes: 6 additions & 1 deletion README.md
Expand Up @@ -29,6 +29,10 @@ The following cloud providers are currently supported:
- Alibaba Cloud (alpha)
- Oracle Cloud Infrastructure (alpha)

## Installation

Refer to the [wiki](https://github.com/nccgroup/ScoutSuite/wiki/Setup).

## Usage

Scout Suite is run through the CLI:
Expand All @@ -41,4 +45,5 @@ Once this has completed, it will generate an HTML report including findings and

The above report was generated by running Scout Suite against https://github.com/nccgroup/sadcloud.

Additional information can be found in the [wiki](https://github.com/nccgroup/ScoutSuite/wiki).
Additional information can be found in the [wiki](https://github.com/nccgroup/ScoutSuite/wiki).
There are also a number of handy [tools](https://github.com/nccgroup/ScoutSuite/tree/master/tools) for automation of common tasks.
2 changes: 1 addition & 1 deletion ScoutSuite/__init__.py
@@ -1,5 +1,5 @@
__author__ = 'NCC Group'
__version__ = '5.8.1'
__version__ = '5.9.0'

ERRORS_LIST = []

Expand Down
40 changes: 22 additions & 18 deletions ScoutSuite/__main__.py
Expand Up @@ -206,24 +206,28 @@ async def _run(provider,
print_exception('Authentication failure: {}'.format(e))
return 101
# Create a cloud provider object
cloud_provider = get_provider(provider=provider,
# AWS
profile=profile,
# Azure
subscription_ids=subscription_ids,
all_subscriptions=all_subscriptions,
# GCP
project_id=project_id,
folder_id=folder_id,
organization_id=organization_id,
all_projects=all_projects,
# Other
report_dir=report_dir,
timestamp=timestamp,
services=services,
skipped_services=skipped_services,
programmatic_execution=programmatic_execution,
credentials=credentials)
try:
cloud_provider = get_provider(provider=provider,
# AWS
profile=profile,
# Azure
subscription_ids=subscription_ids,
all_subscriptions=all_subscriptions,
# GCP
project_id=project_id,
folder_id=folder_id,
organization_id=organization_id,
all_projects=all_projects,
# Other
report_dir=report_dir,
timestamp=timestamp,
services=services,
skipped_services=skipped_services,
programmatic_execution=programmatic_execution,
credentials=credentials)
except Exception as e:
print_exception('Initialization failure: {}'.format(e))
return 102

# Create a new report
report_name = report_name if report_name else cloud_provider.get_report_name()
Expand Down
14 changes: 11 additions & 3 deletions ScoutSuite/core/conditions.py
Expand Up @@ -37,7 +37,7 @@ def pass_conditions(all_info, current_path, conditions, unknown_as_pass_conditio
path_to_value, test_name, test_values = condition
path_to_value = fix_path_string(all_info, current_path, path_to_value)
target_obj = get_value_at(all_info, current_path, path_to_value)
if type(test_values) != list:
if type(test_values) != list and type(test_values) != dict:
dynamic_value = re_get_value_at.match(test_values)
if dynamic_value:
test_values = get_value_at(all_info, current_path, dynamic_value.groups()[0], True)
Expand Down Expand Up @@ -140,7 +140,7 @@ def pass_condition(b, test, a):
if not type(a) == list:
a = [a]
for c in b:
if type(c):
if type(c) != dict:
c = str(c)
if c in a:
result = True
Expand All @@ -165,6 +165,12 @@ def pass_condition(b, test, a):
if c in a:
result = False
break
elif test == 'containAtLeastOneMatching':
result = False
for item in b:
if re.match(a, item):
result = True
break

# Regex tests
elif test == 'match':
Expand Down Expand Up @@ -235,6 +241,8 @@ def pass_condition(b, test, a):
if type(b) != list:
b = [b]
for c in b:
if type(c) == dict and 'AWS' in c:
c = c['AWS']
if c != a and not re.match(r'arn:aws:iam:.*?:%s:.*' % a, c):
result = True
break
Expand All @@ -256,7 +264,7 @@ def pass_condition(b, test, a):


def fix_path_string(all_info, current_path, path_to_value):
# Fixes circulare dependency
# Fixes circular dependency
from ScoutSuite.providers.base.configs.browser import get_value_at
# handle nested _GET_VALUE_AT_...
while True:
Expand Down
28 changes: 17 additions & 11 deletions ScoutSuite/core/processingengine.py
Expand Up @@ -21,7 +21,7 @@ def __init__(self, ruleset):
manage_dictionary(self.rules, rule.path, [])
self.rules[rule.path].append(rule)
except Exception as e:
print_exception('Failed to create rule %s: %s' % (rule.path, e))
print_exception('Failed to create rule %s: %s' % (rule.filename, e))

def run(self, cloud_provider, skip_dashboard=False):
# Clean up existing findings
Expand All @@ -35,15 +35,15 @@ def run(self, cloud_provider, skip_dashboard=False):
if not rule.enabled: # or rule.service not in []: # TODO: handle this...
continue

print_debug('Processing %s rule[%s]: "%s"' % (rule.service, rule.filename, rule.description))
print_debug('Processing %s rule "%s" (%s)' % (rule.service, rule.description, rule.filename))
finding_path = rule.path
path = finding_path.split('.')
service = path[0]
manage_dictionary(cloud_provider.services[service], self.ruleset.rule_type, {})
cloud_provider.services[service][self.ruleset.rule_type][rule.key] = {}
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['description'] = rule.description
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['path'] = rule.path
for attr in ['level', 'id_suffix', 'display_path']:
for attr in ['level', 'id_suffix', 'class_suffix', 'display_path']:
if hasattr(rule, attr):
cloud_provider.services[service][self.ruleset.rule_type][rule.key][attr] = getattr(rule, attr)
try:
Expand All @@ -52,15 +52,21 @@ def run(self, cloud_provider, skip_dashboard=False):
cloud_provider.services, cloud_provider.services, path, [], rule, True)
if skip_dashboard:
continue
cloud_provider.services[service][self.ruleset.rule_type][rule.key][
'dashboard_name'] = rule.dashboard_name
cloud_provider.services[service][self.ruleset.rule_type][rule.key][
'checked_items'] = rule.checked_items
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['flagged_items'] = len(
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['items'])
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['dashboard_name'] = \
rule.dashboard_name
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['checked_items'] = \
rule.checked_items
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['flagged_items'] = \
len(cloud_provider.services[service][self.ruleset.rule_type][rule.key]['items'])
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['service'] = rule.service
cloud_provider.services[service][self.ruleset.rule_type][rule.key][
'rationale'] = rule.rationale if hasattr(rule, 'rationale') else 'No description available.'
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['rationale'] = \
rule.rationale if hasattr(rule, 'rationale') else None
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['remediation'] = \
rule.remediation if hasattr(rule, 'remediation') else None
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['compliance'] = \
rule.compliance if hasattr(rule, 'compliance') else None
cloud_provider.services[service][self.ruleset.rule_type][rule.key]['references'] = \
rule.references if hasattr(rule, 'references') else None
except Exception as e:
print_exception('Failed to process rule defined in %s: %s' % (rule.filename, e))
# Fallback if process rule failed to ensure report creation and data dump still happen
Expand Down
5 changes: 4 additions & 1 deletion ScoutSuite/core/rule.py
Expand Up @@ -100,7 +100,10 @@ def set_definition(self, rule_definitions, attributes=None, ip_ranges=None, para
definition = json.loads(string_definition)
# Set special values (IP ranges, AWS account ID, ...)
for condition in definition['conditions']:
if type(condition) != list or len(condition) == 1 or type(condition[2]) == list:
if type(condition) != list \
or len(condition) == 1 \
or type(condition[2]) == list \
or type(condition[2]) == dict:
continue
for testcase in testcases:
result = testcase['regex'].match(condition[2])
Expand Down
18 changes: 12 additions & 6 deletions ScoutSuite/core/utils.py
Expand Up @@ -5,7 +5,7 @@
from six import string_types
import copy

from ScoutSuite.core.console import print_error
from ScoutSuite.core.console import print_exception
from ScoutSuite.core.conditions import pass_conditions, fix_path_string


Expand Down Expand Up @@ -37,9 +37,14 @@ def recurse(all_info, current_info, target_path, current_path, config, add_suffi
setattr(config, 'checked_items', getattr(config, 'checked_items') + 1)
# Test for conditions...
if pass_conditions(all_info, current_path, copy.deepcopy(config.conditions)):
# id_suffix
if add_suffix and hasattr(config, 'id_suffix'):
suffix = fix_path_string(all_info, current_path, config.id_suffix)
current_path.append(suffix)
# class_suffix
if add_suffix and hasattr(config, 'class_suffix'):
suffix = fix_path_string(all_info, current_path, config.class_suffix)
current_path.append(suffix)
results.append('.'.join(current_path))
# Return the flagged items...
return results
Expand Down Expand Up @@ -74,9 +79,10 @@ def recurse(all_info, current_info, target_path, current_path, config, add_suffi
results = results + recurse(all_info, current_info, [], split_current_path,
config, add_suffix)
else:
print_error('Error: unhandled case, typeof(current_info) = %s' % type(current_info))
print_error('Path: %s' % current_path)
print_error('Object: %s' % str(current_info))
print_error('Entry target path: %s' % str(dbg_target_path))
raise Exception
print_exception('Unable to recursively test condition for path {}: '
'unhandled case for \"{}\" type'.format(current_path,
type(current_info)),
additional_details={'current_path': current_path,
'current_info': current_info,
'dbg_target_path': dbg_target_path})
return results

0 comments on commit 8291714

Please sign in to comment.