Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New attack technique: SES enumeration activities #501

Merged
merged 6 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/attack-techniques/AWS/aws.discovery.ses-enumerate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: Enumerate SES
---

# Enumerate SES


<span class="smallcaps w3-badge w3-blue w3-round w3-text-white" title="This attack technique can be detonated multiple times">idempotent</span>

Platform: AWS

## MITRE ATT&CK Tactics


- Discovery

## Description


Simulates an attacker enumerating SES. Attackers frequently use this enumeration technique after having compromised an access key, to use it to launch phishing campaigns or further resell stolen credentials.

<span style="font-variant: small-caps;">Warm-up</span>: None.

<span style="font-variant: small-caps;">Detonation</span>:

- Perform <code>ses:GetAccountSendingEnabled</code> to check if SES sending is enabled.
- Perform <code>ses:GetSendQuota</code> to discover the current [email sending quotas](https://docs.aws.amazon.com/ses/latest/APIReference/API_GetSendQuota.html).
- Perform <code>ses:ListIdentities</code> to discover the list of [identities](https://docs.aws.amazon.com/ses/latest/APIReference/API_ListIdentities.html) in the account.
- If identities are found, use <code>ses:GetIdentityVerificationAttributes</code> (only once) to discover [verification status](https://docs.aws.amazon.com/ses/latest/APIReference/API_GetIdentityVerificationAttributes.html) of each identity.

References:

- https://securitylabs.datadoghq.com/articles/following-attackers-trail-in-aws-methodology-findings-in-the-wild/#most-common-enumeration-techniques
- https://www.invictus-ir.com/news/ransomware-in-the-cloud
- https://unit42.paloaltonetworks.com/compromised-cloud-compute-credentials/#post-125981-_kdq0vw6banab
- https://permiso.io/blog/s/aws-ses-pionage-detecting-ses-abuse/
- https://www.invictus-ir.com/news/the-curious-case-of-dangerdev-protonmail-me


## Instructions

```bash title="Detonate with Stratus Red Team"
stratus detonate aws.discovery.ses-enumerate
```
## Detection


Through CloudTrail's <code>GetAccountSendingEnabled</code>, <code>GetSendQuota</code> and <code>ListIdentities</code> events.
These can be considered suspicious especially when performed by a long-lived access key, or when the calls span across multiple regions.


2 changes: 2 additions & 0 deletions docs/attack-techniques/AWS/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT

- [Download EC2 Instance User Data](./aws.discovery.ec2-download-user-data.md)

- [Enumerate SES](./aws.discovery.ses-enumerate.md)


## Execution

Expand Down
3 changes: 2 additions & 1 deletion docs/attack-techniques/list.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This page contains the list of all Stratus Attack Techniques.
| [Remove VPC Flow Logs](./AWS/aws.defense-evasion.vpc-remove-flow-logs.md) | [AWS](./AWS/index.md) | Defense Evasion |
| [Execute Discovery Commands on an EC2 Instance](./AWS/aws.discovery.ec2-enumerate-from-instance.md) | [AWS](./AWS/index.md) | Discovery |
| [Download EC2 Instance User Data](./AWS/aws.discovery.ec2-download-user-data.md) | [AWS](./AWS/index.md) | Discovery |
| [Enumerate SES](./AWS/aws.discovery.ses-enumerate.md) | [AWS](./AWS/index.md) | Discovery |
| [Launch Unusual EC2 instances](./AWS/aws.execution.ec2-launch-unusual-instances.md) | [AWS](./AWS/index.md) | Execution |
| [Execute Commands on EC2 Instance via User Data](./AWS/aws.execution.ec2-user-data.md) | [AWS](./AWS/index.md) | Execution, Privilege Escalation |
| [Usage of ssm:SendCommand on multiple instances](./AWS/aws.execution.ssm-send-command.md) | [AWS](./AWS/index.md) | Execution |
Expand Down Expand Up @@ -56,7 +57,6 @@ This page contains the list of all Stratus Attack Techniques.
| [Create an Admin GCP Service Account](./GCP/gcp.persistence.create-admin-service-account.md) | [GCP](./GCP/index.md) | Persistence, Privilege Escalation |
| [Create a GCP Service Account Key](./GCP/gcp.persistence.create-service-account-key.md) | [GCP](./GCP/index.md) | Persistence, Privilege Escalation |
| [Invite an External User to a GCP Project](./GCP/gcp.persistence.invite-external-user.md) | [GCP](./GCP/index.md) | Persistence |
| [Impersonate GCP Service Accounts](./GCP/gcp.privilege-escalation.impersonate-service-accounts.md) | [GCP](./GCP/index.md) | Privilege Escalation |
| [Dump All Secrets](./kubernetes/k8s.credential-access.dump-secrets.md) | [Kubernetes](./kubernetes/index.md) | Credential Access |
| [Steal Pod Service Account Token](./kubernetes/k8s.credential-access.steal-serviceaccount-token.md) | [Kubernetes](./kubernetes/index.md) | Credential Access |
| [Create Admin ClusterRole](./kubernetes/k8s.persistence.create-admin-clusterrole.md) | [Kubernetes](./kubernetes/index.md) | Persistence, Privilege Escalation |
Expand All @@ -65,3 +65,4 @@ This page contains the list of all Stratus Attack Techniques.
| [Container breakout via hostPath volume mount](./kubernetes/k8s.privilege-escalation.hostpath-volume.md) | [Kubernetes](./kubernetes/index.md) | Privilege Escalation |
| [Privilege escalation through node/proxy permissions](./kubernetes/k8s.privilege-escalation.nodes-proxy.md) | [Kubernetes](./kubernetes/index.md) | Privilege Escalation |
| [Run a Privileged Pod](./kubernetes/k8s.privilege-escalation.privileged-pod.md) | [Kubernetes](./kubernetes/index.md) | Privilege Escalation |
| [Impersonate GCP Service Accounts](./GCP/gcp.privilege-escalation.impersonate-service-accounts.md) | [GCP](./GCP/index.md) | Privilege Escalation |
7 changes: 7 additions & 0 deletions docs/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ AWS:
- Discovery
platform: AWS
isIdempotent: true
- id: aws.discovery.ses-enumerate
name: Enumerate SES
isSlow: false
mitreAttackTactics:
- Discovery
platform: AWS
isIdempotent: true
Execution:
- id: aws.execution.ec2-launch-unusual-instances
name: Launch Unusual EC2 instances
Expand Down
10 changes: 6 additions & 4 deletions v2/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ 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.24.1
github.com/aws/aws-sdk-go-v2 v1.26.1
github.com/aws/aws-sdk-go-v2/config v1.25.11
github.com/aws/aws-sdk-go-v2/credentials v1.16.9
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.4
Expand All @@ -23,9 +23,11 @@ require (
github.com/aws/aws-sdk-go-v2/service/route53resolver v1.25.0
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.2
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.25.2
github.com/aws/aws-sdk-go-v2/service/ses v1.22.4
github.com/aws/aws-sdk-go-v2/service/sesv2 v1.27.3
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.2
github.com/aws/aws-sdk-go-v2/service/sts v1.26.2
github.com/aws/smithy-go v1.19.0
github.com/aws/smithy-go v1.20.2
github.com/cenkalti/backoff/v4 v4.2.1
github.com/fatih/color v1.13.0
github.com/golang-jwt/jwt v3.2.2+incompatible
Expand All @@ -49,8 +51,8 @@ require (
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.3 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.8 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.3 // indirect
Expand Down
20 changes: 12 additions & 8 deletions v2/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU=
github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4=
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.3 h1:Zx9+31KyB8wQna6SXFWOewlgoY5uGdDAu6PTOEU3OQI=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.3/go.mod h1:zxbEJhRdKTH1nqS2qu6UJ7zGe25xaHxZXaC2CvuQFnA=
github.com/aws/aws-sdk-go-v2/config v1.25.11 h1:RWzp7jhPRliIcACefGkKp03L0Yofmd2p8M25kbiyvno=
Expand All @@ -46,10 +46,10 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.9 h1:FZVFahMyZle6WcogZCOxo6D
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.9/go.mod h1:kjq7REMIkxdtcEC9/4BVXjOsNY5isz6jQbEgk6osRTU=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.4 h1:TUCNKBd4/JEefsZDxo5deRmrRRPZHqGyBYiUAeBKOWU=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.4/go.mod h1:egDkcl+zsgFqS6VO142bKboip5Pe1sNMwN55Xy38QsM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 h1:vF+Zgd9s+H4vOXd5BMaPWykta2a6Ih0AKLq/X6NYKn4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10/go.mod h1:6BkRjejp/GR4411UGqkX8+wFMbFbqsUIimfK4XjOKR4=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 h1:nYPe006ktcqUji8S2mqXf9c/7NdiKriOwMvWQHgYztw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10/go.mod h1:6UV4SZkVvmODfXKql4LCbaZUpF7HO2BX38FgBf9ZOLw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc=
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.2.8 h1:abKT+RuM1sdCNZIGIfZpLkvxEX3Rpsto019XG/rkYG8=
Expand Down Expand Up @@ -84,6 +84,10 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.47.2 h1:DLSAG8zpJV2pYsU+UPkj1IEZghyBn
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.2/go.mod h1:thjZng67jGsvMyVZnSxlcqKyLwB0XTG8bHIRZPTJ+Bs=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.25.2 h1:JKbfiLwEqJp8zaOAOn6AVSMS96gdwP3TjBMvZYsbxqE=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.25.2/go.mod h1:pbBOMK8UicdDK11zsPSGbpFh9Xwbd1oD3t7pSxXgNxU=
github.com/aws/aws-sdk-go-v2/service/ses v1.22.4 h1:MNU3UWV47ylAAdlU+VxuyItYfuGGp00MvCBxdVAI3kM=
github.com/aws/aws-sdk-go-v2/service/ses v1.22.4/go.mod h1:M/ZQn5uXL4BP1qolIWrlN2SeoUFngJtU/oCwR4WOfZU=
github.com/aws/aws-sdk-go-v2/service/sesv2 v1.27.3 h1:8KP71cUPALMQxs8lhGiWcwdtqv1wsogigS7StDHq0IE=
github.com/aws/aws-sdk-go-v2/service/sesv2 v1.27.3/go.mod h1:WIpmp3q5Iw1AEhotd5OL03OFc0kOUoLPcqKFzcAOImU=
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.2 h1:lmdmYCvG1EJKGLEsUsYDNO6MwZyBZROrRg04Vrb5TwA=
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.2/go.mod h1:pHJ1md/3F3WkYfZ4JKOllPfXQi4NiWk7NxbeOD53HQc=
github.com/aws/aws-sdk-go-v2/service/sso v1.18.2 h1:xJPydhNm0Hiqct5TVKEuHG7weC0+sOs4MUnd7A5n5F4=
Expand All @@ -92,8 +96,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.2 h1:8dU9zqA77C5egbU6yd4hFLai
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.2/go.mod h1:7Lt5mjQ8x5rVdKqg+sKKDeuwoszDJIIPmkd8BVsEdS0=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.2 h1:fFrLsy08wEbAisqW3KDl/cPHrF43GmV79zXB9EwJiZw=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.2/go.mod h1:7Ld9eTqocTvJqqJ5K/orbSDwmGcpRdlDiLjz2DO+SL8=
github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
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=
Expand Down
94 changes: 94 additions & 0 deletions v2/internal/attacktechniques/aws/discovery/ses-enumerate/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package aws

import (
"context"
_ "embed"
"fmt"
"github.com/datadog/stratus-red-team/v2/pkg/stratus"
"github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack"
"log"

"github.com/aws/aws-sdk-go-v2/service/ses"
)

func init() {
stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{
ID: "aws.discovery.ses-enumerate",
FriendlyName: "Enumerate SES",
Description: `
Simulates an attacker enumerating SES. Attackers frequently use this enumeration technique after having compromised an access key, to use it to launch phishing campaigns or further resell stolen credentials.

Warm-up: None.

Detonation:

- Perform <code>ses:GetAccountSendingEnabled</code> to check if SES sending is enabled.
- Perform <code>ses:GetSendQuota</code> to discover the current [email sending quotas](https://docs.aws.amazon.com/ses/latest/APIReference/API_GetSendQuota.html).
- Perform <code>ses:ListIdentities</code> to discover the list of [identities](https://docs.aws.amazon.com/ses/latest/APIReference/API_ListIdentities.html) in the account.
- If identities are found, use <code>ses:GetIdentityVerificationAttributes</code> (only once) to discover [verification status](https://docs.aws.amazon.com/ses/latest/APIReference/API_GetIdentityVerificationAttributes.html) of each identity.

References:

- https://securitylabs.datadoghq.com/articles/following-attackers-trail-in-aws-methodology-findings-in-the-wild/#most-common-enumeration-techniques
- https://www.invictus-ir.com/news/ransomware-in-the-cloud
- https://unit42.paloaltonetworks.com/compromised-cloud-compute-credentials/#post-125981-_kdq0vw6banab
- https://permiso.io/blog/s/aws-ses-pionage-detecting-ses-abuse/
- https://www.invictus-ir.com/news/the-curious-case-of-dangerdev-protonmail-me
`,
Detection: `
Through CloudTrail's <code>GetAccountSendingEnabled</code>, <code>GetSendQuota</code> and <code>ListIdentities</code> events.
These can be considered suspicious especially when performed by a long-lived access key, or when the calls span across multiple regions.
`,
Platform: stratus.AWS,
IsIdempotent: true,
MitreAttackTactics: []mitreattack.Tactic{mitreattack.Discovery},
Detonate: detonate,
})
}

func detonate(_ map[string]string, providers stratus.CloudProviders) error {
awsConnection := providers.AWS().GetConnection()
sesClient := ses.NewFromConfig(awsConnection)

log.Println("Checking is SES e-mail sending is enabled in the current region")
result, err := sesClient.GetAccountSendingEnabled(context.Background(), &ses.GetAccountSendingEnabledInput{})
if err != nil {
return fmt.Errorf("unable to check if SES sending is enabled: %w", err)
}
if result.Enabled {
log.Println("SES e-mail sending is enabled")
} else {
log.Println("SES e-mail sending is disabled")
}

log.Println("Enumerating verified SES identities using ses:ListIdentities")
identities, err := sesClient.ListIdentities(context.Background(), &ses.ListIdentitiesInput{})
if err != nil {
return fmt.Errorf("unable to list SES identities: %w", err)
}

if len(identities.Identities) == 0 {
log.Println("No verified SES identities found")
} else {
log.Printf("Found %d verified SES identities", len(identities.Identities))
verificationAttributes, err := sesClient.GetIdentityVerificationAttributes(context.Background(), &ses.GetIdentityVerificationAttributesInput{
Identities: identities.Identities,
})
if err != nil {
return fmt.Errorf("unable to get identity verification attributes: %w", err)
}
for identity := range verificationAttributes.VerificationAttributes {
log.Printf("- Identity %s has verification status '%s'", identity, verificationAttributes.VerificationAttributes[identity].VerificationStatus)
}
}

log.Println("Enumerating SES quotas")
quotas, err := sesClient.GetSendQuota(context.Background(), &ses.GetSendQuotaInput{})
if err != nil {
return fmt.Errorf("unable to get SES quotas: %w", err)
}

log.Printf("Current quotas: max24hoursend: %d, maxsendrate: %d, sentlast24hours: %d\n", int(quotas.Max24HourSend), int(quotas.MaxSendRate), int(quotas.SentLast24Hours))

return nil
}
1 change: 1 addition & 0 deletions v2/internal/attacktechniques/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/defense-evasion/vpc-remove-flow-logs"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/discovery/ec2-enumerate-from-instance"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/discovery/ec2-get-user-data"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/discovery/ses-enumerate"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/execution/ec2-launch-unusual-instances"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/execution/ec2-user-data"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/execution/ssm-send-command"
Expand Down
Loading