Skip to content

Commit 496d2e2

Browse files
[New] AWS Credentials Used from GitHub Actions and Non-CI/CD Infra (#5956)
* [New] AWS Credentials Used from GitHub Actions and Non-CI/CD Infrastructure Detects AWS access keys that are used from both GitHub Actions CI/CD infrastructure and non-CI/CD infrastructure. This pattern indicates potential credential theft where an attacker who has stolen AWS credentials configured as GitHub Actions secrets and is using them from their own infrastructure. * Update initial_access_github_actions_oidc_credentials_used_from_suspicious_network.toml * ++ * Update initial_access_github_actions_oidc_credentials_used_from_suspicious_network.toml --------- Co-authored-by: shashank-elastic <91139415+shashank-elastic@users.noreply.github.com>
1 parent 2177135 commit 496d2e2

1 file changed

Lines changed: 162 additions & 0 deletions

File tree

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
[metadata]
2+
creation_date = "2026/04/21"
3+
integration = ["aws"]
4+
maturity = "production"
5+
updated_date = "2026/04/21"
6+
7+
[rule]
8+
author = ["Elastic"]
9+
description = """
10+
Detects AWS access keys that are used from both GitHub Actions CI/CD infrastructure and non-CI/CD infrastructure.
11+
This pattern indicates potential credential theft where an attacker who has stolen AWS credentials configured as GitHub
12+
Actions secrets and is using them from their own infrastructure.
13+
"""
14+
false_positives = [
15+
"""
16+
AWS credentials legitimately shared between GitHub Actions and another Microsoft/Azure service
17+
may trigger this rule. Verify whether the non-CI/CD source IP is expected for the workload.
18+
""",
19+
"""
20+
GitHub Actions self-hosted runners running on non-Microsoft/Amazon/Google infrastructure will
21+
appear as suspicious. Add the ASN of your self-hosted runner infrastructure to the is_cicd_infra
22+
allowlist.
23+
""",
24+
]
25+
from = "now-7d"
26+
interval = "1h"
27+
language = "esql"
28+
license = "Elastic License v2"
29+
name = "AWS Credentials Used from GitHub Actions and Non-CI/CD Infrastructure"
30+
note = """## Triage and analysis
31+
32+
### Investigating AWS Credentials Used from GitHub Actions and Non-CI/CD Infrastructure
33+
34+
This rule detects when an AWS access key appears in CloudTrail from both GitHub Actions runners
35+
(identified by Microsoft ASN or the `github-actions` user agent string) and from infrastructure
36+
outside the expected CI/CD provider ASNs. This is a strong indicator that AWS credentials stored
37+
as GitHub repository or organization secrets have been exfiltrated and are being used by an
38+
attacker from their own infrastructure.
39+
40+
### Possible investigation steps
41+
42+
- Identify which GitHub repository owns the credential by cross-referencing the access key ID with
43+
your GitHub Actions workflow configurations and AWS IAM user/role assignments.
44+
- Review the suspicious source IPs and ASNs — residential ISPs, VPN providers, or budget hosting
45+
providers are high-confidence indicators of credential theft.
46+
- Check the actions performed from the suspicious source — `sts:GetCallerIdentity` followed by
47+
enumeration calls (`ListBuckets`, `DescribeInstances`, `ListUsers`) is a common attacker recon
48+
pattern after credential theft.
49+
- Review the user agent strings from the suspicious source — `aws-cli` or `boto3` from a non-runner
50+
IP confirms manual/scripted usage outside CI/CD.
51+
- Check GitHub audit logs for recent workflow changes, new collaborators, or secret access events
52+
that could indicate how the credential was stolen.
53+
- Determine if the credential is a long-lived IAM user key or a temporary STS session — temporary
54+
credentials from `AssumeRoleWithWebIdentity` (OIDC) are less likely to be exfiltrated but still
55+
possible.
56+
57+
### Response and remediation
58+
59+
- Immediately rotate the compromised AWS access key in IAM and update the GitHub repository/org secret.
60+
- Review and revoke any resources created or modified by the suspicious source IP using CloudTrail
61+
event history filtered by the access key ID.
62+
- Audit the GitHub repository for signs of compromise — check for unauthorized workflow modifications,
63+
new secrets, or suspicious pull requests that could have exfiltrated the credential.
64+
- Implement OIDC-based authentication (`aws-actions/configure-aws-credentials` with `role-to-assume`)
65+
instead of long-lived access keys to eliminate the credential theft vector entirely.
66+
- If using OIDC, add IP condition policies to the IAM role trust policy to restrict
67+
`AssumeRoleWithWebIdentity` to known GitHub runner IP ranges.
68+
- Enable GitHub's secret scanning and push protection to detect accidental credential exposure in
69+
code or logs.
70+
"""
71+
references = [
72+
"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services",
73+
"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html",
74+
]
75+
risk_score = 73
76+
rule_id = "b8c7d6e5-f4a3-4b2c-9d8e-7f6a5b4c3d2e"
77+
severity = "high"
78+
tags = [
79+
"Domain: Cloud",
80+
"Data Source: AWS",
81+
"Data Source: Amazon Web Services",
82+
"Data Source: AWS CloudTrail",
83+
"Data Source: AWS IAM",
84+
"Use Case: Threat Detection",
85+
"Tactic: Initial Access",
86+
"Tactic: Lateral Movement",
87+
"Resources: Investigation Guide",
88+
]
89+
timestamp_override = "event.ingested"
90+
type = "esql"
91+
92+
query = '''
93+
from logs-aws.cloudtrail-* metadata _id, _version, _index
94+
95+
| WHERE event.dataset == "aws.cloudtrail"
96+
AND aws.cloudtrail.user_identity.access_key_id IS NOT NULL
97+
AND @timestamp >= NOW() - 7 days
98+
AND source.as.organization.name IS NOT NULL
99+
100+
// AWS API key used from github actions
101+
| EVAL is_aws_github = user_agent.original LIKE "*aws-credentials-for-github-actions"
102+
103+
// non CI/CD related ASN
104+
| EVAL is_not_cicd_infra = not source.as.organization.name IN ("Microsoft Corporation", "Amazon.com, Inc.", "Amazon Technologies Inc.", "Google LLC")
105+
106+
| STATS Esql.is_github_aws_key = MAX(CASE(is_aws_github, 1, 0)),
107+
Esql.has_suspicious_asn = MAX(CASE(is_not_cicd_infra, 1, 0)),
108+
Esql.last_seen_suspicious_asn = MAX(CASE(is_not_cicd_infra, @timestamp, NULL)),
109+
Esql.source_ip_values = VALUES(source.address),
110+
Esql.source_asn_values = VALUES(source.as.organization.name) BY aws.cloudtrail.user_identity.access_key_id, user.name, cloud.account.id
111+
112+
// AWS API key tied to a GH action used from unusual ASN (non CI/CD infra)
113+
| WHERE Esql.is_github_aws_key == 1 AND Esql.has_suspicious_asn == 1
114+
115+
// avoid alert duplicates within 1h interval
116+
AND Esql.last_seen_suspicious_asn >= NOW() - 1 hour
117+
118+
| KEEP user.name, aws.cloudtrail.user_identity.access_key_id, Esql.*
119+
'''
120+
121+
[rule.investigation_fields]
122+
field_names = [
123+
"aws.cloudtrail.user_identity.access_key_id",
124+
"user.name"
125+
]
126+
127+
[[rule.threat]]
128+
framework = "MITRE ATT&CK"
129+
130+
[[rule.threat.technique]]
131+
id = "T1078"
132+
name = "Valid Accounts"
133+
reference = "https://attack.mitre.org/techniques/T1078/"
134+
135+
[[rule.threat.technique.subtechnique]]
136+
id = "T1078.004"
137+
name = "Cloud Accounts"
138+
reference = "https://attack.mitre.org/techniques/T1078/004/"
139+
140+
[rule.threat.tactic]
141+
id = "TA0001"
142+
name = "Initial Access"
143+
reference = "https://attack.mitre.org/tactics/TA0001/"
144+
145+
146+
[[rule.threat]]
147+
framework = "MITRE ATT&CK"
148+
149+
[[rule.threat.technique]]
150+
id = "T1550"
151+
name = "Use Alternate Authentication Material"
152+
reference = "https://attack.mitre.org/techniques/T1550/"
153+
154+
[[rule.threat.technique.subtechnique]]
155+
id = "T1550.001"
156+
name = "Application Access Token"
157+
reference = "https://attack.mitre.org/techniques/T1550/001/"
158+
159+
[rule.threat.tactic]
160+
id = "TA0008"
161+
name = "Lateral Movement"
162+
reference = "https://attack.mitre.org/tactics/TA0008/"

0 commit comments

Comments
 (0)