diff --git a/docs/attack-techniques/AWS/aws.credential-access.secretsmanager-batch-retrieve-secrets.md b/docs/attack-techniques/AWS/aws.credential-access.secretsmanager-batch-retrieve-secrets.md new file mode 100755 index 00000000..965c7a58 --- /dev/null +++ b/docs/attack-techniques/AWS/aws.credential-access.secretsmanager-batch-retrieve-secrets.md @@ -0,0 +1,98 @@ +--- +title: Retrieve a High Number of Secrets Manager secrets (Batch) +--- + +# Retrieve a High Number of Secrets Manager secrets (Batch) + + + idempotent + +Platform: AWS + +## MITRE ATT&CK Tactics + + +- Credential Access + +## Description + + +Retrieves a high number of Secrets Manager secrets by batch, through secretsmanager:BatchGetSecretValue (released Novemeber 2023). +An attacker may attempt to retrieve a high number of secrets by batch, to avoid detection and generate fewer calls. Note that the batch size is limited to 20 secrets. + + +Warm-up: + +- Create multiple secrets in Secrets Manager. + +Detonation: + +- Dump all secrets by batch of 10, using secretsmanager:BatchGetSecretValue. + +References: + +- https://aws.amazon.com/blogs/security/how-to-use-the-batchgetsecretsvalue-api-to-improve-your-client-side-applications-with-aws-secrets-manager/ + + +## Instructions + +```bash title="Detonate with Stratus Red Team" +stratus detonate aws.credential-access.secretsmanager-batch-retrieve-secrets +``` +## Detection + + +Identify principals that attempt to retrieve secrets by batch, through CloudTrail's BatchGetSecretValue event. Sample event: + +```json +{ + "eventSource": "secretsmanager.amazonaws.com", + "eventName": "BatchGetSecretValue", + "requestParameters": { + "filters": [ + { + "key": "tag-key", + "values": [ + "StratusRedTeam" + ] + } + ] + }, + "responseElements": null, + "readOnly": true, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "012345678901" +} +``` + +Although BatchGetSecretValue requires a list of secret IDs or a filter, an attacker may use a catch-all filter to retrieve all secrets by batch: + +```json hl_lines="6-11" +{ + "eventSource": "secretsmanager.amazonaws.com", + "eventName": "BatchGetSecretValue", + "requestParameters": { + "filters": [ + { + "key": "tag-key", + "values": [ + "!tagKeyThatWillNeverExist" + ] + } + ] + }, + "responseElements": null, + "readOnly": true, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "012345678901" +} +``` + +The following may be use to tune the detection, or validate findings: + +- Principals who do not usually call GetBatchSecretValue +- Attempts to call GetBatchSecretValue resulting in access denied errors +- Principals calling GetBatchSecretValue in several regions in a short period of time + diff --git a/docs/attack-techniques/AWS/index.md b/docs/attack-techniques/AWS/index.md index 24f8eecb..8249cd7f 100755 --- a/docs/attack-techniques/AWS/index.md +++ b/docs/attack-techniques/AWS/index.md @@ -10,6 +10,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT - [Steal EC2 Instance Credentials](./aws.credential-access.ec2-steal-instance-credentials.md) +- [Retrieve a High Number of Secrets Manager secrets (Batch)](./aws.credential-access.secretsmanager-batch-retrieve-secrets.md) + - [Retrieve a High Number of Secrets Manager secrets](./aws.credential-access.secretsmanager-retrieve-secrets.md) - [Retrieve And Decrypt SSM Parameters](./aws.credential-access.ssm-retrieve-securestring-parameters.md) @@ -83,12 +85,12 @@ Note that some Stratus attack techniques may correspond to more than a single AT - [Backdoor Lambda Function Through Resource-Based Policy](./aws.persistence.lambda-backdoor-function.md) +- [Add a Malicious Lambda Extension](./aws.persistence.lambda-layer-extension.md) + - [Overwrite Lambda Function Code](./aws.persistence.lambda-overwrite-code.md) - [Create an IAM Roles Anywhere trust anchor](./aws.persistence.rolesanywhere-create-trust-anchor.md) -- [Add a Malicious Lambda Extension](./aws.persistence.lambda-layer-extension.md) - ## Privilege Escalation @@ -100,7 +102,7 @@ Note that some Stratus attack techniques may correspond to more than a single AT - [Create a Login Profile on an IAM User](./aws.persistence.iam-create-user-login-profile.md) -- [Create an IAM Roles Anywhere trust anchor](./aws.persistence.rolesanywhere-create-trust-anchor.md) - - [Add a Malicious Lambda Extension](./aws.persistence.lambda-layer-extension.md) +- [Create an IAM Roles Anywhere trust anchor](./aws.persistence.rolesanywhere-create-trust-anchor.md) + diff --git a/docs/attack-techniques/list.md b/docs/attack-techniques/list.md index 79e4fbe3..36533815 100755 --- a/docs/attack-techniques/list.md +++ b/docs/attack-techniques/list.md @@ -11,6 +11,7 @@ This page contains the list of all Stratus Attack Techniques. | :----: | :------: | :------------------: | | [Retrieve EC2 Password Data](./AWS/aws.credential-access.ec2-get-password-data.md) | [AWS](./AWS/index.md) | Credential Access | | [Steal EC2 Instance Credentials](./AWS/aws.credential-access.ec2-steal-instance-credentials.md) | [AWS](./AWS/index.md) | Credential Access | +| [Retrieve a High Number of Secrets Manager secrets (Batch)](./AWS/aws.credential-access.secretsmanager-batch-retrieve-secrets.md) | [AWS](./AWS/index.md) | Credential Access | | [Retrieve a High Number of Secrets Manager secrets](./AWS/aws.credential-access.secretsmanager-retrieve-secrets.md) | [AWS](./AWS/index.md) | Credential Access | | [Retrieve And Decrypt SSM Parameters](./AWS/aws.credential-access.ssm-retrieve-securestring-parameters.md) | [AWS](./AWS/index.md) | Credential Access | | [Delete CloudTrail Trail](./AWS/aws.defense-evasion.cloudtrail-delete.md) | [AWS](./AWS/index.md) | Defense Evasion | @@ -37,9 +38,9 @@ This page contains the list of all Stratus Attack Techniques. | [Create an administrative IAM User](./AWS/aws.persistence.iam-create-admin-user.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation | | [Create a Login Profile on an IAM User](./AWS/aws.persistence.iam-create-user-login-profile.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation | | [Backdoor Lambda Function Through Resource-Based Policy](./AWS/aws.persistence.lambda-backdoor-function.md) | [AWS](./AWS/index.md) | Persistence | +| [Add a Malicious Lambda Extension](./AWS/aws.persistence.lambda-layer-extension.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation | | [Overwrite Lambda Function Code](./AWS/aws.persistence.lambda-overwrite-code.md) | [AWS](./AWS/index.md) | Persistence | | [Create an IAM Roles Anywhere trust anchor](./AWS/aws.persistence.rolesanywhere-create-trust-anchor.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation | -| [Add a Malicious Lambda Extension](./AWS/aws.persistence.lambda-layer-extension.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation | | [Execute Command on Virtual Machine using Custom Script Extension](./azure/azure.execution.vm-custom-script-extension.md) | [Azure](./azure/index.md) | Execution | | [Execute Commands on Virtual Machine using Run Command](./azure/azure.execution.vm-run-command.md) | [Azure](./azure/index.md) | Execution | | [Export Disk Through SAS URL](./azure/azure.exfiltration.disk-export.md) | [Azure](./azure/index.md) | Exfiltration | diff --git a/docs/index.yaml b/docs/index.yaml index 33aea7bc..d64942f6 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -14,6 +14,13 @@ AWS: - Credential Access platform: AWS isIdempotent: true + - id: aws.credential-access.secretsmanager-batch-retrieve-secrets + name: Retrieve a High Number of Secrets Manager secrets (Batch) + isSlow: false + mitreAttackTactics: + - Credential Access + platform: AWS + isIdempotent: true - id: aws.credential-access.secretsmanager-retrieve-secrets name: Retrieve a High Number of Secrets Manager secrets isSlow: false @@ -207,6 +214,14 @@ AWS: - Persistence platform: AWS isIdempotent: false + - id: aws.persistence.lambda-layer-extension + name: Add a Malicious Lambda Extension + isSlow: false + mitreAttackTactics: + - Persistence + - Privilege Escalation + platform: AWS + isIdempotent: true - id: aws.persistence.lambda-overwrite-code name: Overwrite Lambda Function Code isSlow: false @@ -222,14 +237,6 @@ AWS: - Privilege Escalation platform: AWS isIdempotent: false - - id: aws.persistence.lambda-layer-extension - name: Add a Malicious Lambda Extension - isSlow: false - mitreAttackTactics: - - Persistence - - Privilege Escalation - platform: AWS - isIdempotent: true Privilege Escalation: - id: aws.execution.ec2-user-data name: Execute Commands on EC2 Instance via User Data @@ -263,22 +270,22 @@ AWS: - Privilege Escalation platform: AWS isIdempotent: false - - id: aws.persistence.rolesanywhere-create-trust-anchor - name: Create an IAM Roles Anywhere trust anchor + - id: aws.persistence.lambda-layer-extension + name: Add a Malicious Lambda Extension isSlow: false mitreAttackTactics: - Persistence - Privilege Escalation platform: AWS - isIdempotent: false - - id: aws.persistence.lambda-layer-extension - name: Add a Malicious Lambda Extension + isIdempotent: true + - id: aws.persistence.rolesanywhere-create-trust-anchor + name: Create an IAM Roles Anywhere trust anchor isSlow: false mitreAttackTactics: - Persistence - Privilege Escalation platform: AWS - isIdempotent: true + isIdempotent: false GCP: Exfiltration: - id: gcp.exfiltration.share-compute-disk diff --git a/v2/go.mod b/v2/go.mod index 408219d7..09ef42cb 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -8,22 +8,22 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 - github.com/aws/aws-sdk-go-v2 v1.21.0 - github.com/aws/aws-sdk-go-v2/config v1.18.37 - github.com/aws/aws-sdk-go-v2/credentials v1.13.35 + github.com/aws/aws-sdk-go-v2 v1.23.1 + github.com/aws/aws-sdk-go-v2/config v1.25.5 + github.com/aws/aws-sdk-go-v2/credentials v1.16.4 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.81 github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.19.1 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.63.1 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.137.1 github.com/aws/aws-sdk-go-v2/service/iam v1.18.20 github.com/aws/aws-sdk-go-v2/service/lambda v1.24.7 github.com/aws/aws-sdk-go-v2/service/organizations v1.16.13 github.com/aws/aws-sdk-go-v2/service/rds v1.26.1 github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.0.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.38.5 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.3 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.24.0 github.com/aws/aws-sdk-go-v2/service/ssm v1.31.0 - github.com/aws/aws-sdk-go-v2/service/sts v1.21.5 - github.com/aws/smithy-go v1.14.2 + github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 + github.com/aws/smithy-go v1.17.0 github.com/cenkalti/backoff/v4 v4.2.1 github.com/fatih/color v1.13.0 github.com/golang-jwt/jwt v3.2.2+incompatible @@ -46,17 +46,17 @@ require ( github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.42 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.13.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/go-logr/logr v1.2.3 // indirect diff --git a/v2/go.sum b/v2/go.sum index 9b5f3684..0529c199 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -36,43 +36,60 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= github.com/aws/aws-sdk-go-v2 v1.17.0/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= -github.com/aws/aws-sdk-go-v2 v1.21.0 h1:gMT0IW+03wtYJhRqTVYn0wLzwdnK9sRMcxmtfGzRdJc= github.com/aws/aws-sdk-go-v2 v1.21.0/go.mod h1:/RfNgGmRxI+iFOB1OeJUyxiU+9s88k3pfHvDagGEp0M= +github.com/aws/aws-sdk-go-v2 v1.23.1 h1:qXaFsOOMA+HsZtX8WoCa+gJnbyW7qyFFBlPqvTSzbaI= +github.com/aws/aws-sdk-go-v2 v1.23.1/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13 h1:OPLEkmhXf6xFPiz0bLeDArZIDx1NNS4oJyG4nv3Gct0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13/go.mod h1:gpAbvyDGQFozTEmlTFO8XcQKHzubdq0LzRyJpG6MiXM= github.com/aws/aws-sdk-go-v2/config v1.18.37 h1:RNAfbPqw1CstCooHaTPhScz7z1PyocQj0UL+l95CgzI= github.com/aws/aws-sdk-go-v2/config v1.18.37/go.mod h1:8AnEFxW9/XGKCbjYDCJy7iltVNyEI9Iu9qC21UzhhgQ= +github.com/aws/aws-sdk-go-v2/config v1.25.5 h1:UGKm9hpQS2hoK8CEJ1BzAW8NbUpvwDJJ4lyqXSzu8bk= +github.com/aws/aws-sdk-go-v2/config v1.25.5/go.mod h1:Bf4gDvy4ZcFIK0rqDu1wp9wrubNba2DojiPB2rt6nvI= github.com/aws/aws-sdk-go-v2/credentials v1.13.35 h1:QpsNitYJu0GgvMBLUIYu9H4yryA5kMksjeIVQfgXrt8= github.com/aws/aws-sdk-go-v2/credentials v1.13.35/go.mod h1:o7rCaLtvK0hUggAGclf76mNGGkaG5a9KWlp+d9IpcV8= +github.com/aws/aws-sdk-go-v2/credentials v1.16.4 h1:i7UQYYDSJrtc30RSwJwfBKwLFNnBTiICqAJ0pPdum8E= +github.com/aws/aws-sdk-go-v2/credentials v1.16.4/go.mod h1:Kdh/okh+//vQ/AjEt81CjvkTo64+/zIE4OewP7RpfXk= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.11 h1:uDZJF1hu0EVT/4bogChk8DyjSF6fof6uL/0Y26Ma7Fg= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.11/go.mod h1:TEPP4tENqBGO99KwVpV9MlOX4NSrSLP8u3KRy2CDwA8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 h1:KehRNiVzIfAcj6gw98zotVbb/K67taJE0fkfgM6vzqU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5/go.mod h1:VhnExhw6uXy9QzetvpXDolo1/hjhx4u9qukBGkuUwjs= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.81 h1:PQ9zoe2GEoTVSVPuNtjNrKeVPvyVPWesETMPb7KB3Fk= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.81/go.mod h1:EztVLIU9xGitjdZ1TyHWL9IcNx4952FlqKJe6GLG2z4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.24/go.mod h1:ghMzB/j2wRbPx5/4jPYxJdOtCG2ggrtY01j8K7FMBDA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41 h1:22dGT7PneFMx4+b3pz7lMTRyN8ZKH7M2cW4GP9yUS2g= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41/go.mod h1:CrObHAuPneJBlfEJ5T3szXOUkLEThaGfvnhTf33buas= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 h1:LAm3Ycm9HJfbSCd5I+wqC2S9Ej7FPrgr5CQoOljJZcE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4/go.mod h1:xEhvbJcyUf/31yfGSQBe01fukXwXJ0gxDp7rLfymWE0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.18/go.mod h1:fkQKYK/jUhCL/wNS1tOPrlYhr9vqutjCz4zZC1wBE1s= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35 h1:SijA0mgjV8E+8G45ltVHs0fvKpTj8xmZJ3VwhGKtUSI= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35/go.mod h1:SJC1nEVVva1g3pHAIdCp7QsRIkMmLAgoDquQ9Rr8kYw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 h1:4GV0kKZzUxiWxSVpn/9gwR0g21NF1Jsyduzo9rHgC/Q= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4/go.mod h1:dYvTNAggxDZy6y1AF7YDwXsPuHFy/VNEpEI/2dWK9IU= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.42 h1:GPUcE/Yq7Ur8YSUk6lVkoIMWnJNO0HT18GUzCWCgCI0= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.42/go.mod h1:rzfdUlfA+jdgLDmPKjd3Chq9V7LVLYo1Nz++Wb91aRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 h1:uR9lXYjdPX0xY+NhvaJ4dD8rpSRz5VY81ccIIoNG+lw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4 h1:6lJvvkQ9HmbHZ4h/IEwclwv2mrTW8Uq1SOB/kXy0mfw= github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4/go.mod h1:1PrKYwxTM+zjpw9Y41KFtoJCQrJ34Z47Y4VgVbfndjo= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.19.1 h1:MvowO2iiy2oKDGxFMe9ZnNxs5uKiIP3x1NThF9/dLns= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.19.1/go.mod h1:VcHQDIdzSaBM9l0RMG0Eu7n92rnWMgl5JPanjvwcdJk= github.com/aws/aws-sdk-go-v2/service/ec2 v1.63.1 h1:jSS5gynKz4XaGcs6m25idCTN+tvPkRJ2WedSWCcZEjI= github.com/aws/aws-sdk-go-v2/service/ec2 v1.63.1/go.mod h1:0+6fPoY0SglgzQUs2yml7X/fup12cMlVumJufh5npRQ= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.137.1 h1:J/N4ydefXQZIwKBDPtvrhxrIuP/vaaYKnAsy3bKVIvU= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.137.1/go.mod h1:hrBzQzlQQRmiaeYRQPr0SdSx6fdqP+5YcGhb97LCt8M= github.com/aws/aws-sdk-go-v2/service/iam v1.18.20 h1:Kv+0rsPs7+Q7b2t9UAVUZONv2qdfSInySmBC9kaCyd8= github.com/aws/aws-sdk-go-v2/service/iam v1.18.20/go.mod h1:pDBRPE4AibneAh4P6fZuU3eUkAgYirM88o2M2MxIXlg= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14 h1:m0QTSI6pZYJTk5WSKx3fm5cNW/DCicVzULBgU/6IyD0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14/go.mod h1:dDilntgHy9WnHXsh7dDtUPgHKEfTJIBUTHM8OWm0f/0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 h1:rpkF4n0CyFcrJUG/rNNohoTmhtWlFTRI4BsZOh9PvLs= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1/go.mod h1:l9ymW25HOqymeU2m1gbUQ3rUIsTwKs8gYHXkqDQUhiI= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36 h1:eev2yZX7esGRjqRbnVk1UxMLw4CyVZDpZXRCcy75oQk= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36/go.mod h1:lGnOkH9NJATw0XEPcAknFBj3zzNTEGRHtSw+CwC1YTg= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35 h1:CdzPW9kKitgIiLV1+MHobfR5Xg25iYnyzWZhyQuSlDI= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35/go.mod h1:QGF2Rs33W5MaN9gYdEQOBBFPLwTZkEhRwI33f7KIG0o= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 h1:rdovz3rEu0vZKbzoMYPTehp0E8veoE9AyfzqCr5Eeao= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4/go.mod h1:aYCGNjyUCUelhofxlZyj63srdxWUSsBSGg5l6MCuXuE= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4 h1:v0jkRigbSD6uOdwcaUQmgEwG1BkPfAPDqaeNt/29ghg= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4/go.mod h1:LhTyt8J04LL+9cIt7pYJ5lbS/U98ZmXovLOR/4LUsk8= github.com/aws/aws-sdk-go-v2/service/lambda v1.24.7 h1:oL0zUTbYgb9J48x/C/Vg7WoM92W+i24Lk7EwCB/ExVs= @@ -85,24 +102,34 @@ github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.0.10 h1:FYBnb1z07t3qpAFddD github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.0.10/go.mod h1:61Oc8W4jS9kp9xNyrBkzir82bq5AV7moeXLkHR6nzLY= github.com/aws/aws-sdk-go-v2/service/s3 v1.38.5 h1:A42xdtStObqy7NGvzZKpnyNXvoOmm+FENobZ0/ssHWk= github.com/aws/aws-sdk-go-v2/service/s3 v1.38.5/go.mod h1:rDGMZA7f4pbmTtPOk5v5UM2lmX6UAbRnMDJeDvnH7AM= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.3 h1:d5S+OhXne5O3cIo999RARy/N1dgXW2ldWgD53qbEAP4= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.3/go.mod h1:+X/VSQcuvHPWPRlM64HoWUJAPwsD86KpU9Z52lrsodM= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.24.0 h1:nHbWXaoEhGk5JNxwinY0lSTCtmIeWJ3tO8eR3Z85jG4= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.24.0/go.mod h1:LDD9wCQ1tvjMIWEIFPvZ8JgJsEOjded+X5jav9tD/zg= github.com/aws/aws-sdk-go-v2/service/ssm v1.31.0 h1:zBiXS2v+ycKZ61bTBR1jGqIJhEW7Qjcl8c/mrkUNeog= github.com/aws/aws-sdk-go-v2/service/ssm v1.31.0/go.mod h1:JtkQSJFGEovwP6s+guH5Ap7iUemh3nMqHtg5liCv9ok= github.com/aws/aws-sdk-go-v2/service/sso v1.13.5 h1:oCvTFSDi67AX0pOX3PuPdGFewvLRU2zzFSrTsgURNo0= github.com/aws/aws-sdk-go-v2/service/sso v1.13.5/go.mod h1:fIAwKQKBFu90pBxx07BFOMJLpRUGu8VOzLJakeY+0K4= +github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 h1:CdsSOGlFF3Pn+koXOIpTtvX7st0IuGsZ8kJqcWMlX54= +github.com/aws/aws-sdk-go-v2/service/sso v1.17.3/go.mod h1:oA6VjNsLll2eVuUoF2D+CMyORgNzPEW/3PyUdq6WQjI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.5 h1:dnInJb4S0oy8aQuri1mV6ipLlnZPfnsDNB9BGO9PDNY= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.5/go.mod h1:yygr8ACQRY2PrEcy3xsUI357stq2AxnFM6DIsR9lij4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 h1:cbRqFTVnJV+KRpwFl76GJdIZJKKCdTPnjUZ7uWh3pIU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1/go.mod h1:hHL974p5auvXlZPIjJTblXJpbkfK4klBczlsEaMCGVY= github.com/aws/aws-sdk-go-v2/service/sts v1.21.5 h1:CQBFElb0LS8RojMJlxRSo/HXipvTZW2S44Lt9Mk2aYQ= github.com/aws/aws-sdk-go-v2/service/sts v1.21.5/go.mod h1:VC7JDqsqiwXukYEDjoHh9U0fOJtNWh04FPQz4ct4GGU= +github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 h1:yEvZ4neOQ/KpUqyR+X0ycUTW/kVRNR4nDZ38wStHGAA= +github.com/aws/aws-sdk-go-v2/service/sts v1.25.4/go.mod h1:feTnm2Tk/pJxdX+eooEsxvlvTWBvDm6CasRZ+JOs2IY= github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/aws/smithy-go v1.14.2 h1:MJU9hqBGbvWZdApzpvoF2WAIJDbtjK2NDJSiJP7HblQ= github.com/aws/smithy-go v1.14.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/smithy-go v1.17.0 h1:wWJD7LX6PBV6etBUwO0zElG0nWN9rUhp0WdYeHSHAaI= +github.com/aws/smithy-go v1.17.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -118,10 +145,12 @@ github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= diff --git a/v2/internal/attacktechniques/aws/credential-access/secretsmanager-batch-retrieve-secrets/main.go b/v2/internal/attacktechniques/aws/credential-access/secretsmanager-batch-retrieve-secrets/main.go new file mode 100644 index 00000000..61432f1f --- /dev/null +++ b/v2/internal/attacktechniques/aws/credential-access/secretsmanager-batch-retrieve-secrets/main.go @@ -0,0 +1,136 @@ +package aws + +import ( + "context" + _ "embed" + "errors" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" + "github.com/datadog/stratus-red-team/v2/pkg/stratus" + "github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack" + "log" + "strconv" +) + +//go:embed main.tf +var tf []byte + +const code = "```" + +// BatchSize how many secrets to retrieve per call +// default value is 10 - the max value is 20 +// we stick to 10 to generate more BatchGetSecretValue calls without the need for too many actual secrets +const BatchSize = 10 + +func init() { + stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{ + ID: "aws.credential-access.secretsmanager-batch-retrieve-secrets", + FriendlyName: "Retrieve a High Number of Secrets Manager secrets (Batch)", + Description: ` +Retrieves a high number of Secrets Manager secrets by batch, through secretsmanager:BatchGetSecretValue (released Novemeber 2023). +An attacker may attempt to retrieve a high number of secrets by batch, to avoid detection and generate fewer calls. Note that the batch size is limited to 20 secrets. + + +Warm-up: + +- Create multiple secrets in Secrets Manager. + +Detonation: + +- Dump all secrets by batch of ` + strconv.Itoa(BatchSize) + `, using secretsmanager:BatchGetSecretValue. + +References: + +- https://aws.amazon.com/blogs/security/how-to-use-the-batchgetsecretsvalue-api-to-improve-your-client-side-applications-with-aws-secrets-manager/ +`, + Detection: ` +Identify principals that attempt to retrieve secrets by batch, through CloudTrail's BatchGetSecretValue event. Sample event: + +` + code + `json +{ + "eventSource": "secretsmanager.amazonaws.com", + "eventName": "BatchGetSecretValue", + "requestParameters": { + "filters": [ + { + "key": "tag-key", + "values": [ + "StratusRedTeam" + ] + } + ] + }, + "responseElements": null, + "readOnly": true, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "012345678901" +} +` + code + ` + +Although BatchGetSecretValue requires a list of secret IDs or a filter, an attacker may use a catch-all filter to retrieve all secrets by batch: + +` + code + `json hl_lines="6-11" +{ + "eventSource": "secretsmanager.amazonaws.com", + "eventName": "BatchGetSecretValue", + "requestParameters": { + "filters": [ + { + "key": "tag-key", + "values": [ + "!tagKeyThatWillNeverExist" + ] + } + ] + }, + "responseElements": null, + "readOnly": true, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "012345678901" +} +` + code + ` + +The following may be use to tune the detection, or validate findings: + +- Principals who do not usually call GetBatchSecretValue +- Attempts to call GetBatchSecretValue resulting in access denied errors +- Principals calling GetBatchSecretValue in several regions in a short period of time`, + Platform: stratus.AWS, + IsIdempotent: true, + MitreAttackTactics: []mitreattack.Tactic{mitreattack.CredentialAccess}, + PrerequisitesTerraformCode: tf, + Detonate: detonate, + }) +} + +func detonate(_ map[string]string, providers stratus.CloudProviders) error { + secretsManagerClient := secretsmanager.NewFromConfig(providers.AWS().GetConnection()) + + log.Println("Retrieving secrets by batch of " + strconv.Itoa(BatchSize) + " using BatchGetSecretValue...") + paginator := secretsmanager.NewBatchGetSecretValuePaginator(secretsManagerClient, &secretsmanager.BatchGetSecretValueInput{ + Filters: []types.Filter{ + {Key: types.FilterNameStringTypeTagKey, Values: []string{"StratusRedTeam"}}, + // note: you could use the filter below to dump all secrets by batch + // {Key: types.FilterNameStringTypeTagKey, Values: []string{"!iwillprobablyneverexist"}}, + }, + MaxResults: aws.Int32(BatchSize), + }) + + for paginator.HasMorePages() { + batchSecretsResponse, err := paginator.NextPage(context.Background()) + if err != nil { + return errors.New("unable to call BatchGetSecretValue: " + err.Error()) + } + + log.Println("Successfully retrieved a batch of " + strconv.Itoa(len(batchSecretsResponse.SecretValues)) + " secrets") + for _, secret := range batchSecretsResponse.SecretValues { + fmt.Println("\t" + *secret.Name + " = " + *secret.SecretString) + } + } + + return nil +} diff --git a/v2/internal/attacktechniques/aws/credential-access/secretsmanager-batch-retrieve-secrets/main.tf b/v2/internal/attacktechniques/aws/credential-access/secretsmanager-batch-retrieve-secrets/main.tf new file mode 100644 index 00000000..e83e3ceb --- /dev/null +++ b/v2/internal/attacktechniques/aws/credential-access/secretsmanager-batch-retrieve-secrets/main.tf @@ -0,0 +1,46 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 3.0" + } + } +} +provider "aws" { + skip_region_validation = true + skip_credentials_validation = true + skip_get_ec2_platforms = true + default_tags { + tags = { + StratusRedTeam = true + } + } +} + +locals { + num_secrets = 42 + resource_prefix = "stratus-red-team-retrieve--batch-secret" +} + +resource "random_string" "secrets" { + count = local.num_secrets + length = 16 + min_lower = 16 +} + +resource "aws_secretsmanager_secret" "secrets" { + count = local.num_secrets + name = "${local.resource_prefix}-${count.index}" + + recovery_window_in_days = 0 +} + +resource "aws_secretsmanager_secret_version" "secret-values" { + count = local.num_secrets + secret_id = aws_secretsmanager_secret.secrets[count.index].id + secret_string = random_string.secrets[count.index].result +} + +output "display" { + value = format("%s Secrets Manager secrets ready", local.num_secrets) +} \ No newline at end of file diff --git a/v2/internal/attacktechniques/main.go b/v2/internal/attacktechniques/main.go index f41ab15e..6b38d6c9 100644 --- a/v2/internal/attacktechniques/main.go +++ b/v2/internal/attacktechniques/main.go @@ -3,6 +3,7 @@ package attacktechniques import ( _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/credential-access/ec2-get-password-data" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/credential-access/ec2-steal-instance-credentials" + _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/credential-access/secretsmanager-batch-retrieve-secrets" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/credential-access/secretsmanager-retrieve-secrets" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/credential-access/ssm-retrieve-securestring-parameters" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/defense-evasion/cloudtrail-delete" @@ -29,9 +30,9 @@ import ( _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/persistence/iam-create-admin-user" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/persistence/iam-create-user-login-profile" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/persistence/lambda-backdoor-function" + _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/persistence/lambda-overwrite-code" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/persistence/rolesanywhere-create-trust-anchor" - _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/azure/execution/vm-custom-script-extension" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/azure/execution/vm-run-command" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/azure/exfiltration/disk-export"