-
Notifications
You must be signed in to change notification settings - Fork 671
[New Rule] AWS Lambda Execution Role Credentials Used Outside Lambda #6292
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
Open
bryans3c
wants to merge
10
commits into
main
Choose a base branch
from
rule/aws-lambda-creds-used-outside
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+151
−0
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
f66f00e
[New Rule] AWS Lambda Event Source Mapping Creation
bryans3c e3de389
Update persistence_lambda_event_source_mapping_created.toml
bryans3c 6852a96
[New Rule] AWS Lambda Function Deletion
bryans3c 91fb5dc
[New Rule] AWS Lambda Execution Role Credentials Used Outside Lambda
bryans3c 2630413
Delete rules/integrations/aws/impact_lambda_function_deleted.toml
bryans3c 296726d
Delete rules/integrations/aws/persistence_lambda_event_source_mapping…
bryans3c b512e4a
Update defense_evasion_lambda_execution_role_credentials_used_outside…
bryans3c 9eb79bc
Apply suggestion from @terrancedejesus
bryans3c 08b7e09
Apply suggestions from code review
bryans3c 56d9efb
Update time window and formatting in AWS Lambda rule
bryans3c File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
151 changes: 151 additions & 0 deletions
151
...tegrations/aws/defense_evasion_lambda_execution_role_credentials_used_outside_lambda.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only time I see this invoked_by value is when |
||
| 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", | ||
| ] | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.