diff --git a/rules/integrations/aws/defense_evasion_lambda_execution_role_credentials_used_outside_lambda.toml b/rules/integrations/aws/defense_evasion_lambda_execution_role_credentials_used_outside_lambda.toml new file mode 100644 index 00000000000..9b4cd5bf93c --- /dev/null +++ b/rules/integrations/aws/defense_evasion_lambda_execution_role_credentials_used_outside_lambda.toml @@ -0,0 +1,151 @@ +[metadata] +creation_date = "2026/06/18" +integration = ["aws"] +maturity = "production" +updated_date = "2026/06/18" + +[rule] +author = ["Elastic"] +description = """ +Identifies a single AWS Lambda execution-role credential (a temporary assumed-role access key) that is used both from +inside the Lambda execution environment and from outside it within the same window. When a function runs, its temporary +credentials are presented with the Lambda runtime user agent (containing "exec-env/AWS_Lambda") or with a request +invoked by "lambda.amazonaws.com". An adversary who exfiltrates those credentials, typically through a server-side +request forgery or remote code execution flaw in the function, can replay them from their own host, where the same +access key appears without the Lambda runtime markers and from an unrelated source. Observing the same temporary key +both inside and outside the runtime is a strong indicator of stolen Lambda credentials being abused. +""" +false_positives = [ + """ + Some architectures proxy or forward Lambda activity in ways that can strip the runtime user agent, and certain AWS + service integrations may act on a function's behalf. Validate the access key, the principal in + `aws.cloudtrail.user_identity.arn`, the external source IPs, and the user agents observed outside the runtime before + treating the activity as malicious. Known proxies or service integrations can be tuned out after validation. + """, +] +from = "now-61m" +interval = "60m" +language = "esql" +license = "Elastic License v2" +name = "AWS Lambda Execution Role Credentials Used Outside Function" +note = """## Triage and analysis + +### Investigating AWS Lambda Execution Role Credentials Used Outside Function + +AWS Lambda functions receive temporary credentials for their execution role and use them from within the managed runtime. CloudTrail records those calls with a user agent containing `exec-env/AWS_Lambda` or with `aws.cloudtrail.user_identity.invoked_by` set to `lambda.amazonaws.com`. If the same temporary access key is also seen making calls without those runtime markers, the credentials were almost certainly extracted from the function (for example via SSRF or RCE against the function code) and replayed from an attacker-controlled location. + +This rule aggregates CloudTrail by the temporary access key and flags keys that were used both inside and outside the Lambda runtime in the same window. + +### Possible investigation steps + +- Review `Esql.source_ips` and `Esql.user_agents` for the external (non-runtime) activity and determine whether the source IPs and clients are expected for the workload. +- Map `aws.cloudtrail.user_identity.arn` to the Lambda function and its execution role, and review the function's code, dependencies, and recent changes for an SSRF/RCE or credential-exposure path. +- Examine `Esql.actions` for the operations performed with the credential outside the runtime, especially data access, IAM, or STS calls that exceed the function's normal behavior. +- Determine the blast radius of the execution role's permissions and whether any sensitive actions succeeded. +- Pivot on the external source IPs across other identities and accounts for signs of broader credential abuse. + +### False positive analysis + +- Proxies, log-forwarding layers, or service integrations that act on a function's behalf may occasionally present a Lambda credential without the runtime user agent. Validate the external source and client, and tune out known benign patterns on `aws.cloudtrail.user_identity.arn` or the observed user agents. + +### Response and remediation + +- If the credential abuse is confirmed, terminate active sessions and rotate or revoke the execution role's permissions; the temporary key cannot be individually revoked, so remove or restrict the role's trust and permissions. +- Patch the function's credential-exposure path (for example the SSRF/RCE vulnerability) and redeploy from a known-good source. +- Review and reduce the execution role's permissions to least privilege, and assess any actions performed with the stolen credential for data exposure or further compromise. + +### Additional information + +- [Using AWS Lambda environment variables (runtime identifiers)](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) +""" +references = [ + "https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html", + "https://docs.aws.amazon.com/lambda/latest/dg/logging-using-cloudtrail.html", + "https://hackingthe.cloud/aws/exploitation/lambda-steal-iam-credentials/", +] +risk_score = 73 +rule_id = "0ae9b6c5-1deb-4ed4-9337-659dd701dfbc" +severity = "high" +tags = [ + "Domain: Cloud", + "Data Source: AWS", + "Data Source: Amazon Web Services", + "Data Source: AWS Lambda", + "Use Case: Threat Detection", + "Tactic: Defense Evasion", + "Resources: Investigation Guide", +] +timestamp_override = "event.ingested" +type = "esql" + +query = ''' +from logs-aws.cloudtrail-* + +| where + aws.cloudtrail.user_identity.type == "AssumedRole" + and aws.cloudtrail.user_identity.access_key_id IS NOT NULL + +| eval is_lambda_call = case( + user_agent.original LIKE "*exec-env/AWS_Lambda*" + or aws.cloudtrail.user_identity.invoked_by == "lambda.amazonaws.com", + 1, 0) + +| stats + Esql.lambda_runtime_call_sum = sum(is_lambda_call), + Esql.total_call_count = count(), + Esql.source_ip_values = values(source.ip), + Esql.user_agent_values = values(user_agent.original), + Esql.event_action_values = values(event.action) + by + aws.cloudtrail.user_identity.access_key_id, + aws.cloudtrail.user_identity.arn, + cloud.account.id + +| eval Esql.external_call_count = Esql.total_call_count - Esql.lambda_runtime_call_sum + +| where Esql.lambda_runtime_call_sum > 0 and Esql.external_call_count > 0 + +| keep + aws.cloudtrail.user_identity.access_key_id, + aws.cloudtrail.user_identity.arn, + cloud.account.id, + Esql.lambda_runtime_call_sum, + Esql.external_call_count, + Esql.source_ip_values, + Esql.user_agent_values, + Esql.event_action_values + +| sort Esql.external_call_count desc +''' + + +[[rule.threat]] +framework = "MITRE ATT&CK" +[[rule.threat.technique]] +id = "T1078" +name = "Valid Accounts" +reference = "https://attack.mitre.org/techniques/T1078/" +[[rule.threat.technique.subtechnique]] +id = "T1078.004" +name = "Cloud Accounts" +reference = "https://attack.mitre.org/techniques/T1078/004/" + + + +[rule.threat.tactic] +id = "TA0005" +name = "Defense Evasion" +reference = "https://attack.mitre.org/tactics/TA0005/" + +[rule.investigation_fields] +field_names = [ + "aws.cloudtrail.user_identity.access_key_id", + "aws.cloudtrail.user_identity.arn", + "cloud.account.id", + "Esql.lambda_runtime_call_sum", + "Esql.external_call_count", + "Esql.source_ip_values", + "Esql.user_agent_values", + "Esql.event_action_values", +] +