Skip to content

Commit 3c05bcf

Browse files
authored
Merge pull request #253 from HackTricks-wiki/update_Threat_Actors_Using_AWS_WorkMail_in_Phishing_Campa_20260127_183842
Threat Actors Using AWS WorkMail in Phishing Campaigns
2 parents 9f30d3f + 6be7ed9 commit 3c05bcf

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@
310310
- [AWS - Step Functions Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md)
311311
- [AWS - STS Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md)
312312
- [AWS - VPN Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md)
313+
- [Readme](pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md)
313314
- [AWS - Privilege Escalation](pentesting-cloud/aws-security/aws-privilege-escalation/README.md)
314315
- [AWS - Apigateway Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md)
315316
- [AWS - AppRunner Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md)

src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ aws sesv2 send-custom-verification-email --email-address <value> --template-name
8080

8181
Still to test.
8282

83+
## WorkMail pivot to bypass SES sandbox
84+
85+
When `ses:GetAccount` shows the account is still in the SES sandbox and `ses:ListIdentities` returns no verified senders, attackers can **pivot to WorkMail** to send immediately (no sandbox and higher default quotas) by creating orgs, verifying domains, and registering mailboxes.
86+
87+
{{#ref}}
88+
../aws-workmail-post-exploitation/README.md
89+
{{#endref}}
90+
91+
## References
92+
93+
- [Threat Actors Using AWS WorkMail in Phishing Campaigns](https://www.rapid7.com/blog/post/dr-threat-actors-aws-workmail-phishing-campaigns)
94+
8395
{{#include ../../../../banners/hacktricks-training.md}}
8496

8597

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# AWS - WorkMail Post Exploitation
2+
3+
{{#include ../../../../banners/hacktricks-training.md}}
4+
5+
## Abusing WorkMail to bypass SES sandbox
6+
7+
Even if SES is stuck in the **sandbox** (verified-recipient only, ~200 msgs/24h, 1 msg/s), WorkMail has no equivalent restriction. An attacker with long-term keys can spin up disposable mail infra and start sending immediately:
8+
9+
1. **Create a WorkMail org (region-scoped)**
10+
```bash
11+
aws workmail create-organization --region us-east-1 --alias temp-mail --directory-id <dir-id-if-reusing>
12+
```
13+
2. **Verify attacker-controlled domains** (WorkMail invokes SES APIs as `workmail.amazonaws.com`):
14+
```bash
15+
aws ses verify-domain-identity --domain attacker-domain.com
16+
aws ses verify-domain-dkim --domain attacker-domain.com
17+
```
18+
3. **Provision mailbox users** and register them:
19+
```bash
20+
aws workmail create-user --organization-id <org-id> --name marketing --display-name "Marketing"
21+
aws workmail register-to-work-mail --organization-id <org-id> --entity-id <user-id> --email marketing@attacker-domain.com
22+
```
23+
24+
Notes:
25+
- Default **recipient cap** documented by AWS: **100,000 external recipients/day per org** (aggregated across users).
26+
- Domain verification activity will appear in CloudTrail under SES but with **`invokedBy`: `workmail.<region>.amazonaws.com`**, so SES verification events can belong to WorkMail setup rather than SES campaigns.
27+
- WorkMail mailbox users become **application-layer persistence** independent from IAM users.
28+
29+
## Sending paths & telemetry gaps
30+
31+
### Web client (WorkMail UI)
32+
- Sends surface as **`ses:SendRawEmail`** events in CloudTrail.
33+
- `userIdentity.type` = `AWSService`, `invokedBy/sourceIPAddress/userAgent` = `workmail.<region>.amazonaws.com`, so the **true client IP is hidden**.
34+
- `requestParameters` still leak sender (`source`, `fromArn`, `sourceArn`, configuration set) to correlate with newly verified domains/mailboxes.
35+
36+
### SMTP (stealthiest)
37+
- Endpoint: `smtp.mail.<region>.awsapps.com:465` (SMTP over SSL) with the mailbox password.
38+
- **No CloudTrail data events** are generated for SMTP delivery, even when SES data events are enabled.
39+
- Ideal detection points are **org/domain/user provisioning** and SES identity ARNs referenced in subsequent web-sent `SendRawEmail` events.
40+
41+
<details>
42+
<summary>Example SMTP send via WorkMail</summary>
43+
44+
```python
45+
import smtplib
46+
from email.message import EmailMessage
47+
48+
SMTP_SERVER = "smtp.mail.us-east-1.awsapps.com"
49+
SMTP_PORT = 465
50+
EMAIL_ADDRESS = "marketing@attacker-domain.com"
51+
EMAIL_PASSWORD = "SuperSecretPassword!"
52+
53+
target = "victim@example.com" # can be unverified/external
54+
msg = EmailMessage()
55+
msg["Subject"] = "WorkMail SMTP"
56+
msg["From"] = EMAIL_ADDRESS
57+
msg["To"] = target
58+
msg.set_content("Delivered via WorkMail SMTP")
59+
60+
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as smtp:
61+
smtp.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
62+
smtp.send_message(msg)
63+
```
64+
65+
</details>
66+
67+
## Detection considerations
68+
69+
- If WorkMail is unnecessary, block it via **SCPs** (`workmail:*` deny) at the org level.
70+
- Alert on provisioning: `workmail:CreateOrganization`, `workmail:CreateUser`, `workmail:RegisterToWorkMail`, and SES verifications with `invokedBy=workmail.amazonaws.com` (`ses:VerifyDomainIdentity`, `ses:VerifyDomainDkim`).
71+
- Watch for anomalous **`ses:SendRawEmail`** events where the identity ARNs reference new domains and the source IP/UA equals `workmail.<region>.amazonaws.com`.
72+
73+
## References
74+
75+
- [Threat Actors Using AWS WorkMail in Phishing Campaigns](https://www.rapid7.com/blog/post/dr-threat-actors-aws-workmail-phishing-campaigns)
76+
- [AWS WorkMail limits](https://docs.aws.amazon.com/workmail/latest/adminguide/limits.html)
77+
78+
{{#include ../../../../banners/hacktricks-training.md}}

src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,20 @@ aws iam list-mfa-devices
9090
aws iam list-virtual-mfa-devices
9191
```
9292

93+
### Stealth permission confirmation via intentional failures
94+
95+
When `List*` or simulator APIs are blocked, you can **confirm mutating permissions without creating durable resources** by forcing predictable validation errors. AWS still evaluates IAM before returning these errors, so seeing the error proves the caller has the action:
96+
97+
```bash
98+
# Confirm iam:CreateUser without creating a new principal (fails only after authz)
99+
aws iam create-user --user-name <existing_user> # -> EntityAlreadyExistsException
100+
101+
# Confirm iam:CreateLoginProfile while learning password policy requirements
102+
aws iam create-login-profile --user-name <target_user> --password lower --password-reset-required # -> PasswordPolicyViolationException
103+
```
104+
105+
These attempts still generate CloudTrail events (with `errorCode` set) but avoid leaving new IAM artifacts, making them useful for **low-noise permission validation** during interactive recon.
106+
93107
### Permissions Brute Force
94108

95109
If you are interested in your own permissions but you don't have access to query IAM you could always brute-force them.

0 commit comments

Comments
 (0)