# AWS External Account Scanner
> Xenos, is Greek for stranger.
AWSXenos will assess the trust relationships in all the IAM roles, and resource policies for [several AWS services](#aws-iam-access-analyzer-comparison) in an AWS account and give you a breakdown of all the accounts that have trust relationships to your account. It will also highlight whether the trusts have an [external ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) or not.
https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html
This tool reports against the [Trusted Relationship Technique](https://attack.mitre.org/techniques/T1199/) and parts of the [Valid Accounts: Cloud Accounts](https://attack.mitre.org/techniques/T1078/004/) of the ATT&CK Framework.
* For the "known" accounts list AWSXenos uses a modified version of [known AWS Accounts](https://github.com/fwdcloudsec/known_aws_accounts).
* For the Org accounts list, AWSXenos will query AWS Organizations.
* AWS Services are classified separately.
* Everything else falls under unknown account
* For regional services, e.g. KMS, you'll need to run AWSXenos per region.
* You can configure which services you'd like to assess by providing a [config.yaml](awsxenos/config.yaml) file.
## Example
![HTML Report Screenshot](screenshots/report.png)
## Why
Access Analyzer falls short because:
1. You need to enable it in every region.
2. Identified external entities might be known entities. E.g. a trusted third party vendor or a vendor you no longer trust. An Account number is seldom useful.
3. Zone of trust is a fixed set of the AWS organisation. You won’t know if a trust between sandbox->prod has been established.
4. Does not identify AWS Service principals. This is mainly important because of [Wiz's AWSConfig, et al vulnverabilities](http://i.blackhat.com/USA21/Wednesday-Handouts/us-21-Breaking-The-Isolation-Cross-Account-AWS-Vulnerabilities.pdf)
## AWS IAM Access Analyzer comparison
Comparison based on AWS Documentation [1](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) and [2](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html#what-is-access-analyzer-resource-identification), including services or resources outside of docs, e.g. VPC endpoints.
| Service | AWSXenos | Access Analyzer |
| :--: | :--: | :--: |
| S3 Bucket| :white_check_mark: | :white_check_mark: |
| S3 Directory Buckets | :x: | :white_check_mark: |
| S3 Access Points | :x: | :white_check_mark: |
| S3 Bucket ACLs | :white_check_mark: | :white_check_mark: |
| S3 Glacier | :white_check_mark: | :x: |
| IAM | :white_check_mark: | :white_check_mark: |
| KMS | :white_check_mark: | :white_check_mark: |
| Secrets Manager | :white_check_mark: | :white_check_mark: |
| Lambda | :white_check_mark: | :white_check_mark: |
| SNS | :white_check_mark: | :white_check_mark: |
| SQS | :white_check_mark: | :white_check_mark: |
| RDS Snapshots | :x: | :white_check_mark: |
| RDS Cluster Snapshots | :x: | :white_check_mark: |
| ECR | :x: | :white_check_mark: |
| EFS | :white_check_mark: | :white_check_mark: |
| DynamoDB streams | :white_check_mark: | :white_check_mark: |
| DynamoDB tables | :white_check_mark: | :white_check_mark: |
| EBS Snapshots | :x: | :white_check_mark: |
| EventBridge | :white_check_mark: | :x: |
| EventBridge Schema | :x: | :x: |
| Mediastore | :x: | :x: |
| Glue | :x: | :x: |
| Kinesis Data Streams | :white_check_mark: | :x: |
| Lex v2 | :x: | :x: |
| Migration Hub Orchestrator | :x: | :x: |
| OpenSearch | :white_check_mark: | :x: |
| AWS PCA | :x: | :x: |
| Redshift Serverless | :x: | :x: |
| Serverless Application Repository | :x: | :x: |
| SES v2 | :x: | :x: |
| Incident Manager | :x: | :x: |
| Incident Manager Contacts | :x: | :x: |
| VPC endpoints | :white_check_mark: | :x: |
## How to run
### Cli
```sh
pip install AWSXenos
awsxenos --reporttype HTML -w report.html
awsxenos --reporttype JSON -w report.json
```
You will get an HTML and JSON report.
See [example report](example/example.html)
You can configure the services you care about by using [your own config](awsxenos/config.yaml).
### Library
```python
from awsxenos.scan import PreScan
from awsxenos.report import Report
from awsxenos.s3 import S3
#from awsxenos.iam import IAM
# To run everything based on your config.
prescan = PreScan()
results = load_and_run(config_path, prescan.accounts)
r = Report(results, prescan.known_accounts)
# Per service
prescan = PreScan()
aws_service = S3()
findings = aws_service.fetch(prescan.accounts)
r = Report(s.findings, s.known_accounts)
json_summary = r.JSON_report()
html_summary = r.HTML_report()
```
### IAM Permissions
Permissions required to scan all services.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"dynamodb:GetResourcePolicy",
"dynamodb:ListStreams",
"dynamodb:ListTables",
"ec2:DescribeVpcEndpoints",
"elasticfilesystem:DescribeFileSystemPolicy",
"elasticfilesystem:DescribeFileSystems",
"es:DescribeDomains",
"es:ListDomainNames",
"events:ListEventBuses",
"glacier:GetVaultAccessPolicy",
"glacier:ListVaults",
"iam:ListRoles",
"kinesis:GetResourcePolicy",
"kinesis:ListStreams",
"kms:GetKeyPolicy",
"kms:ListKeys",
"lambda:GetPolicy",
"lambda:ListFunctions",
"organizations:DescribeOrganization",
"organizations:ListAccounts",
"s3:GetBucketAcl",
"s3:GetBucketPolicy",
"s3:ListAllMyBuckets",
"secretsmanager:GetResourcePolicy",
"secretsmanager:ListSecrets",
"sns:GetTopicAttributes",
"sns:ListTopics",
"sqs:GetQueueAttributes",
"sqs:ListQueues"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
```
## Development
```sh
python3 -m env venv
source /env/bin/activate
pip install -r requirements.txt
```
1. Create a file with the name of the service.
2. Create a class with the name of the resource that you want from that service
3. Your class must inherit from `Service` and return `Findings`
Example:
```python
class S3(Service):
def fetch(self, accounts: Accounts ) -> Findings:
self._buckets = self.list_account_buckets()
self.policies = self.get_bucket_policies()
return super().collate(accounts, self.policies)
```
4. Add your filename and class to the config
---
## FAQ
### Are there false positives?
Yes. AWSXenos doesn't take into consideration Identity or SCP. It assumes that everything else other than the resource or trust policy _has_ access.
### Is this using an SMT Solver or automated reasoning ?
No. AWSXenos only takes into account resource and IAM trust policies. Maybe in the next project or iteration.
### Why not use [CheckAccessNotGranted](https://docs.aws.amazon.com/access-analyzer/latest/APIReference/API_CheckAccessNotGranted.html) ?
We don't know the set of accounts that shouldn't access the resource or role.
### How does it work ?
AWSXenos currently assesses access based on [https://github.com/Netflix-Skunkworks/policyuniverse](https://github.com/Netflix-Skunkworks/policyuniverse).
## Features
- [x] Use as library
- [x] HTML and JSON output
- [x] Multi-threaded querying of each service
Raw data
{
"_id": null,
"home_page": "https://github.com/AirWalk-Digital/AWSXenos",
"name": "AWSXenos",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "aws iam cross-account roles security",
"author": "Costas Kourmpoglou",
"author_email": "costas.kourmpoglou@airwalkconsulting.com",
"download_url": "https://files.pythonhosted.org/packages/7f/34/7b6f4c0ee1619b95bd8e8ab562ecf737b71d7efe0f167694ae2a2ab6e72e/awsxenos-0.4.0.tar.gz",
"platform": null,
"description": "# AWS External Account Scanner\n\n> Xenos, is Greek for stranger.\n\nAWSXenos will assess the trust relationships in all the IAM roles, and resource policies for [several AWS services](#aws-iam-access-analyzer-comparison) in an AWS account and give you a breakdown of all the accounts that have trust relationships to your account. It will also highlight whether the trusts have an [external ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) or not.\n\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html\n\nThis tool reports against the [Trusted Relationship Technique](https://attack.mitre.org/techniques/T1199/) and parts of the [Valid Accounts: Cloud Accounts](https://attack.mitre.org/techniques/T1078/004/) of the ATT&CK Framework. \n\n* For the \"known\" accounts list AWSXenos uses a modified version of [known AWS Accounts](https://github.com/fwdcloudsec/known_aws_accounts).\n* For the Org accounts list, AWSXenos will query AWS Organizations.\n* AWS Services are classified separately.\n* Everything else falls under unknown account\n* For regional services, e.g. KMS, you'll need to run AWSXenos per region.\n* You can configure which services you'd like to assess by providing a [config.yaml](awsxenos/config.yaml) file.\n\n## Example\n![HTML Report Screenshot](screenshots/report.png)\n\n## Why\n\nAccess Analyzer falls short because:\n\n1. You need to enable it in every region. \n\n2. Identified external entities might be known entities. E.g. a trusted third party vendor or a vendor you no longer trust. An Account number is seldom useful. \n\n3. Zone of trust is a fixed set of the AWS organisation. You won\u2019t know if a trust between sandbox->prod has been established. \n\n4. Does not identify AWS Service principals. This is mainly important because of [Wiz's AWSConfig, et al vulnverabilities](http://i.blackhat.com/USA21/Wednesday-Handouts/us-21-Breaking-The-Isolation-Cross-Account-AWS-Vulnerabilities.pdf)\n\n\n## AWS IAM Access Analyzer comparison \n\nComparison based on AWS Documentation [1](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) and [2](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html#what-is-access-analyzer-resource-identification), including services or resources outside of docs, e.g. VPC endpoints.\n\n\n| Service | AWSXenos | Access Analyzer |\n| :--: | :--: | :--: |\n| S3 Bucket| :white_check_mark: | :white_check_mark: |\n| S3 Directory Buckets | :x: | :white_check_mark: |\n| S3 Access Points | :x: | :white_check_mark: |\n| S3 Bucket ACLs | :white_check_mark: | :white_check_mark: |\n| S3 Glacier | :white_check_mark: | :x: |\n| IAM | :white_check_mark: | :white_check_mark: |\n| KMS | :white_check_mark: | :white_check_mark: |\n| Secrets Manager | :white_check_mark: | :white_check_mark: |\n| Lambda | :white_check_mark: | :white_check_mark: |\n| SNS | :white_check_mark: | :white_check_mark: |\n| SQS | :white_check_mark: | :white_check_mark: |\n| RDS Snapshots | :x: | :white_check_mark: |\n| RDS Cluster Snapshots | :x: | :white_check_mark: |\n| ECR | :x: | :white_check_mark: |\n| EFS | :white_check_mark: | :white_check_mark: |\n| DynamoDB streams | :white_check_mark: | :white_check_mark: |\n| DynamoDB tables | :white_check_mark: | :white_check_mark: |\n| EBS Snapshots | :x: | :white_check_mark: |\n| EventBridge | :white_check_mark: | :x: |\n| EventBridge Schema | :x: | :x: |\n| Mediastore | :x: | :x: |\n| Glue | :x: | :x: |\n| Kinesis Data Streams | :white_check_mark: | :x: |\n| Lex v2 | :x: | :x: |\n| Migration Hub Orchestrator | :x: | :x: |\n| OpenSearch | :white_check_mark: | :x: |\n| AWS PCA | :x: | :x: |\n| Redshift Serverless | :x: | :x: |\n| Serverless Application Repository | :x: | :x: |\n| SES v2 | :x: | :x: |\n| Incident Manager | :x: | :x: |\n| Incident Manager Contacts | :x: | :x: |\n| VPC endpoints | :white_check_mark: | :x: |\n\n## How to run\n\n### Cli\n```sh\npip install AWSXenos\nawsxenos --reporttype HTML -w report.html\nawsxenos --reporttype JSON -w report.json\n```\nYou will get an HTML and JSON report.\n\nSee [example report](example/example.html)\n\nYou can configure the services you care about by using [your own config](awsxenos/config.yaml).\n\n### Library\n\n```python\nfrom awsxenos.scan import PreScan\nfrom awsxenos.report import Report\nfrom awsxenos.s3 import S3\n#from awsxenos.iam import IAM\n\n# To run everything based on your config.\n\nprescan = PreScan()\nresults = load_and_run(config_path, prescan.accounts)\nr = Report(results, prescan.known_accounts)\n\n# Per service\nprescan = PreScan()\naws_service = S3()\nfindings = aws_service.fetch(prescan.accounts)\nr = Report(s.findings, s.known_accounts)\njson_summary = r.JSON_report()\nhtml_summary = r.HTML_report()\n```\n\n### IAM Permissions\n\nPermissions required to scan all services.\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"dynamodb:GetResourcePolicy\",\n \"dynamodb:ListStreams\",\n \"dynamodb:ListTables\",\n \"ec2:DescribeVpcEndpoints\",\n \"elasticfilesystem:DescribeFileSystemPolicy\",\n \"elasticfilesystem:DescribeFileSystems\",\n \"es:DescribeDomains\",\n \"es:ListDomainNames\",\n \"events:ListEventBuses\",\n \"glacier:GetVaultAccessPolicy\",\n \"glacier:ListVaults\",\n \"iam:ListRoles\",\n \"kinesis:GetResourcePolicy\",\n \"kinesis:ListStreams\", \n \"kms:GetKeyPolicy\",\n \"kms:ListKeys\",\n \"lambda:GetPolicy\",\n \"lambda:ListFunctions\",\n \"organizations:DescribeOrganization\",\n \"organizations:ListAccounts\",\n \"s3:GetBucketAcl\",\n \"s3:GetBucketPolicy\",\n \"s3:ListAllMyBuckets\",\n \"secretsmanager:GetResourcePolicy\",\n \"secretsmanager:ListSecrets\",\n \"sns:GetTopicAttributes\",\n \"sns:ListTopics\",\n \"sqs:GetQueueAttributes\",\n \"sqs:ListQueues\"\n ],\n \"Effect\": \"Allow\",\n \"Resource\": \"*\"\n }\n ]\n}\n```\n\n## Development\n\n```sh\npython3 -m env venv\nsource /env/bin/activate\npip install -r requirements.txt\n```\n\n1. Create a file with the name of the service.\n2. Create a class with the name of the resource that you want from that service\n3. Your class must inherit from `Service` and return `Findings`\n\nExample: \n\n```python\nclass S3(Service):\n\n def fetch(self, accounts: Accounts ) -> Findings:\n self._buckets = self.list_account_buckets()\n self.policies = self.get_bucket_policies()\n return super().collate(accounts, self.policies)\n```\n4. Add your filename and class to the config\n\n---\n\n## FAQ\n\n### Are there false positives?\nYes. AWSXenos doesn't take into consideration Identity or SCP. It assumes that everything else other than the resource or trust policy _has_ access. \n\n### Is this using an SMT Solver or automated reasoning ?\nNo. AWSXenos only takes into account resource and IAM trust policies. Maybe in the next project or iteration.\n\n### Why not use [CheckAccessNotGranted](https://docs.aws.amazon.com/access-analyzer/latest/APIReference/API_CheckAccessNotGranted.html) ?\nWe don't know the set of accounts that shouldn't access the resource or role.\n\n### How does it work ?\nAWSXenos currently assesses access based on [https://github.com/Netflix-Skunkworks/policyuniverse](https://github.com/Netflix-Skunkworks/policyuniverse).\n\n## Features\n- [x] Use as library\n- [x] HTML and JSON output \n- [x] Multi-threaded querying of each service \n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Scan and classify cross-account roles and resources in your AWS Account",
"version": "0.4.0",
"project_urls": {
"Homepage": "https://github.com/AirWalk-Digital/AWSXenos"
},
"split_keywords": [
"aws",
"iam",
"cross-account",
"roles",
"security"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "fa984b081ca4b62a69104291a1e99643f9454040f940cb44d695a91bdd1f2609",
"md5": "87fa9faf7bf34da7cc53155618bd650a",
"sha256": "82cdee28b624fae591c5f81ba476085140f20056404f6fb71e6ef2de3bd6422d"
},
"downloads": -1,
"filename": "AWSXenos-0.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "87fa9faf7bf34da7cc53155618bd650a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 36387,
"upload_time": "2024-05-28T08:45:30",
"upload_time_iso_8601": "2024-05-28T08:45:30.440721Z",
"url": "https://files.pythonhosted.org/packages/fa/98/4b081ca4b62a69104291a1e99643f9454040f940cb44d695a91bdd1f2609/AWSXenos-0.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7f347b6f4c0ee1619b95bd8e8ab562ecf737b71d7efe0f167694ae2a2ab6e72e",
"md5": "cf1e9cdd0f1d9bbc927837a34728fe41",
"sha256": "7daeabc647ff87fe500b617176d25d95b688ce1db0e9a8408a1d20a263deeea1"
},
"downloads": -1,
"filename": "awsxenos-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "cf1e9cdd0f1d9bbc927837a34728fe41",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 27993,
"upload_time": "2024-05-28T08:45:32",
"upload_time_iso_8601": "2024-05-28T08:45:32.909946Z",
"url": "https://files.pythonhosted.org/packages/7f/34/7b6f4c0ee1619b95bd8e8ab562ecf737b71d7efe0f167694ae2a2ab6e72e/awsxenos-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-28 08:45:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "AirWalk-Digital",
"github_project": "AWSXenos",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "awsxenos"
}