From d151fe9b85fed2909b4cc6a71e6a66621a9db9b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adan=20=C3=81lvarez?= Date: Thu, 9 Nov 2023 10:38:08 +0100 Subject: [PATCH] New attack technique: Persistence AWS Lambda Layer Extension (#427) * Add lambda-layer-extension technique * build documentation * Minor docs editing * Minor code changes --------- Co-authored-by: Christophe Tafani-Dereeper --- .../AWS/aws.persistence.iam-backdoor-user.md | 1 + .../aws.persistence.iam-create-admin-user.md | 1 + ...rsistence.iam-create-user-login-profile.md | 2 + .../aws.persistence.lambda-layer-extension.md | 51 ++++++++ .../aws.persistence.lambda-overwrite-code.md | 1 + docs/attack-techniques/AWS/index.md | 4 + ...ersistence.create-admin-service-account.md | 1 + docs/attack-techniques/list.md | 1 + docs/index.yaml | 16 +++ .../lambda-layer-extension/main.go | 89 ++++++++++++++ .../lambda-layer-extension/main.tf | 113 ++++++++++++++++++ v2/internal/attacktechniques/main.go | 1 + 12 files changed, 281 insertions(+) create mode 100755 docs/attack-techniques/AWS/aws.persistence.lambda-layer-extension.md create mode 100644 v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.go create mode 100644 v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.tf diff --git a/docs/attack-techniques/AWS/aws.persistence.iam-backdoor-user.md b/docs/attack-techniques/AWS/aws.persistence.iam-backdoor-user.md index ffcc8314..419736c1 100755 --- a/docs/attack-techniques/AWS/aws.persistence.iam-backdoor-user.md +++ b/docs/attack-techniques/AWS/aws.persistence.iam-backdoor-user.md @@ -29,6 +29,7 @@ Establishes persistence by creating an access key on an existing IAM user. - Create an IAM access key on the user. References: + - https://sysdig.com/blog/scarleteel-2-0/ diff --git a/docs/attack-techniques/AWS/aws.persistence.iam-create-admin-user.md b/docs/attack-techniques/AWS/aws.persistence.iam-create-admin-user.md index dbb16dfa..6b85f354 100755 --- a/docs/attack-techniques/AWS/aws.persistence.iam-create-admin-user.md +++ b/docs/attack-techniques/AWS/aws.persistence.iam-create-admin-user.md @@ -29,6 +29,7 @@ Establishes persistence by creating a new IAM user with administrative permissio References: - https://permiso.io/blog/s/approach-to-detection-androxgh0st-greenbot-persistence/ +- https://permiso.io/blog/s/unmasking-guivil-new-cloud-threat-actor/ - https://blog.darklab.hk/2021/07/06/trouble-in-paradise/ - https://expel.com/blog/incident-report-from-cli-to-console-chasing-an-attacker-in-aws/ diff --git a/docs/attack-techniques/AWS/aws.persistence.iam-create-user-login-profile.md b/docs/attack-techniques/AWS/aws.persistence.iam-create-user-login-profile.md index 4458bc9e..00039e13 100755 --- a/docs/attack-techniques/AWS/aws.persistence.iam-create-user-login-profile.md +++ b/docs/attack-techniques/AWS/aws.persistence.iam-create-user-login-profile.md @@ -30,7 +30,9 @@ user intended to be used programmatically through the AWS console usual login pr - Create an IAM Login Profile on the user References: + - https://permiso.io/blog/s/approach-to-detection-androxgh0st-greenbot-persistence/ +- https://permiso.io/blog/s/unmasking-guivil-new-cloud-threat-actor/ - https://blog.darklab.hk/2021/07/06/trouble-in-paradise/ - https://expel.com/blog/incident-report-from-cli-to-console-chasing-an-attacker-in-aws/ diff --git a/docs/attack-techniques/AWS/aws.persistence.lambda-layer-extension.md b/docs/attack-techniques/AWS/aws.persistence.lambda-layer-extension.md new file mode 100755 index 00000000..1e3576d1 --- /dev/null +++ b/docs/attack-techniques/AWS/aws.persistence.lambda-layer-extension.md @@ -0,0 +1,51 @@ +--- +title: Add a Malicious Lambda Extension +--- + +# Add a Malicious Lambda Extension + + + idempotent + +Platform: AWS + +## MITRE ATT&CK Tactics + + +- Persistence +- Privilege Escalation + +## Description + + +Establishes persistence by adding a malicious lambda extension. + +Warm-up: + +- Create a Lambda function and a lambda extension (layer). + +Detonation: + +- Add the extension as a layer to the Lambda function. + +References: + +- https://www.clearvector.com/blog/lambda-spy/ + + +## Instructions + +```bash title="Detonate with Stratus Red Team" +stratus detonate aws.persistence.lambda-layer-extension +``` +## Detection + + +Through CloudTrail's UpdateFunctionConfiguration20150331v2 event. + +While matching this event may be impractical and prone to false positives in most environments, the following can help to craft more precise detections: + +- Identify calls to UpdateFunctionConfiguration20150331v2 where the responseElements field contains layer, indicating that the function's layers were modified. +- Identify calls to UpdateFunctionConfiguration20150331v2 where responseElements.layers includes a layer that's from a different AWS account.' + + diff --git a/docs/attack-techniques/AWS/aws.persistence.lambda-overwrite-code.md b/docs/attack-techniques/AWS/aws.persistence.lambda-overwrite-code.md index 69c8774b..c6fe96cf 100755 --- a/docs/attack-techniques/AWS/aws.persistence.lambda-overwrite-code.md +++ b/docs/attack-techniques/AWS/aws.persistence.lambda-overwrite-code.md @@ -29,6 +29,7 @@ A further, more advanced, use-case could be updating the code to exfiltrate the - Update the Lambda function code. References: + - https://research.splunk.com/cloud/aws_lambda_updatefunctioncode/ - Expel's AWS security mindmap diff --git a/docs/attack-techniques/AWS/index.md b/docs/attack-techniques/AWS/index.md index 5bad5e80..24f8eecb 100755 --- a/docs/attack-techniques/AWS/index.md +++ b/docs/attack-techniques/AWS/index.md @@ -87,6 +87,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT - [Create an IAM Roles Anywhere trust anchor](./aws.persistence.rolesanywhere-create-trust-anchor.md) +- [Add a Malicious Lambda Extension](./aws.persistence.lambda-layer-extension.md) + ## Privilege Escalation @@ -100,3 +102,5 @@ Note that some Stratus attack techniques may correspond to more than a single AT - [Create an IAM Roles Anywhere trust anchor](./aws.persistence.rolesanywhere-create-trust-anchor.md) +- [Add a Malicious Lambda Extension](./aws.persistence.lambda-layer-extension.md) + diff --git a/docs/attack-techniques/GCP/gcp.persistence.create-admin-service-account.md b/docs/attack-techniques/GCP/gcp.persistence.create-admin-service-account.md index 677be981..9a2bb608 100755 --- a/docs/attack-techniques/GCP/gcp.persistence.create-admin-service-account.md +++ b/docs/attack-techniques/GCP/gcp.persistence.create-admin-service-account.md @@ -29,6 +29,7 @@ Establishes persistence by creating a new service account and assigning it - Update the current GCP project's IAM policy to bind the service account to the owner role' References: + - https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/ diff --git a/docs/attack-techniques/list.md b/docs/attack-techniques/list.md index c626a841..79e4fbe3 100755 --- a/docs/attack-techniques/list.md +++ b/docs/attack-techniques/list.md @@ -39,6 +39,7 @@ This page contains the list of all Stratus Attack Techniques. | [Backdoor Lambda Function Through Resource-Based Policy](./AWS/aws.persistence.lambda-backdoor-function.md) | [AWS](./AWS/index.md) | Persistence | | [Overwrite Lambda Function Code](./AWS/aws.persistence.lambda-overwrite-code.md) | [AWS](./AWS/index.md) | Persistence | | [Create an IAM Roles Anywhere trust anchor](./AWS/aws.persistence.rolesanywhere-create-trust-anchor.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation | +| [Add a Malicious Lambda Extension](./AWS/aws.persistence.lambda-layer-extension.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation | | [Execute Command on Virtual Machine using Custom Script Extension](./azure/azure.execution.vm-custom-script-extension.md) | [Azure](./azure/index.md) | Execution | | [Execute Commands on Virtual Machine using Run Command](./azure/azure.execution.vm-run-command.md) | [Azure](./azure/index.md) | Execution | | [Export Disk Through SAS URL](./azure/azure.exfiltration.disk-export.md) | [Azure](./azure/index.md) | Exfiltration | diff --git a/docs/index.yaml b/docs/index.yaml index 9177f1bd..33aea7bc 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -222,6 +222,14 @@ AWS: - Privilege Escalation platform: AWS isIdempotent: false + - id: aws.persistence.lambda-layer-extension + name: Add a Malicious Lambda Extension + isSlow: false + mitreAttackTactics: + - Persistence + - Privilege Escalation + platform: AWS + isIdempotent: true Privilege Escalation: - id: aws.execution.ec2-user-data name: Execute Commands on EC2 Instance via User Data @@ -263,6 +271,14 @@ AWS: - Privilege Escalation platform: AWS isIdempotent: false + - id: aws.persistence.lambda-layer-extension + name: Add a Malicious Lambda Extension + isSlow: false + mitreAttackTactics: + - Persistence + - Privilege Escalation + platform: AWS + isIdempotent: true GCP: Exfiltration: - id: gcp.exfiltration.share-compute-disk diff --git a/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.go b/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.go new file mode 100644 index 00000000..59eaff07 --- /dev/null +++ b/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.go @@ -0,0 +1,89 @@ +package aws + +import ( + "context" + _ "embed" + "errors" + "log" + + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/datadog/stratus-red-team/v2/pkg/stratus" + "github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack" +) + +//go:embed main.tf +var tf []byte + +func init() { + stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{ + ID: "aws.persistence.lambda-layer-extension", + FriendlyName: "Add a Malicious Lambda Extension", + Description: ` +Establishes persistence by adding a malicious lambda extension. + +Warm-up: + +- Create a Lambda function and a lambda extension (layer). + +Detonation: + +- Add the extension as a layer to the Lambda function. + +References: + +- https://www.clearvector.com/blog/lambda-spy/ +`, + Detection: ` +Through CloudTrail's UpdateFunctionConfiguration20150331v2 event. + +While matching this event may be impractical and prone to false positives in most environments, the following can help to craft more precise detections: + +- Identify calls to UpdateFunctionConfiguration20150331v2 where the responseElements field contains layer, indicating that the function's layers were modified. +- Identify calls to UpdateFunctionConfiguration20150331v2 where responseElements.layers includes a layer that's from a different AWS account.' +`, + Platform: stratus.AWS, + PrerequisitesTerraformCode: tf, + IsIdempotent: true, + MitreAttackTactics: []mitreattack.Tactic{mitreattack.Persistence, mitreattack.PrivilegeEscalation}, + Detonate: detonate, + Revert: revert, + }) +} + +func detonate(params map[string]string, providers stratus.CloudProviders) error { + ctx := context.Background() + lambdaClient := lambda.NewFromConfig(providers.AWS().GetConnection()) + lambdaExtensionLayerArn := params["lambda_extension_layer_arn"] + lambdaArn := params["lambda_arn"] + + // Update the function configuration with our layer + _, err := lambdaClient.UpdateFunctionConfiguration(ctx, &lambda.UpdateFunctionConfigurationInput{ + FunctionName: &lambdaArn, + Layers: []string{lambdaExtensionLayerArn}, + }) + + if err != nil { + return errors.New("unable to update function configuration: " + err.Error()) + } + + log.Println("Added simulated malicious layer to Lambda function ", lambdaArn) + return nil +} + +func revert(params map[string]string, providers stratus.CloudProviders) error { + ctx := context.Background() + lambdaArn := params["lambda_arn"] + lambdaClient := lambda.NewFromConfig(providers.AWS().GetConnection()) + + // Update the function configuration with an empty list of layers + _, err := lambdaClient.UpdateFunctionConfiguration(ctx, &lambda.UpdateFunctionConfigurationInput{ + FunctionName: &lambdaArn, + Layers: []string{}, + }) + + if err != nil { + return errors.New("unable to update function configuration: " + err.Error()) + } + log.Printf("Layers have been removed from the Lambda function %s\n", lambdaArn) + return nil +} diff --git a/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.tf b/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.tf new file mode 100644 index 00000000..ddfa52bd --- /dev/null +++ b/v2/internal/attacktechniques/aws/persistence/lambda-layer-extension/main.tf @@ -0,0 +1,113 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} +provider "aws" { + skip_region_validation = true + skip_credentials_validation = true + skip_get_ec2_platforms = true + default_tags { + tags = { + StratusRedTeam = true + } + } +} + +locals { + resource_prefix = "stratus-red-team-lambda-layer" +} + +resource "aws_iam_role" "lambda_role" { + name = "${local.resource_prefix}-lambda-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + "Service" : [ + "lambda.amazonaws.com" + ] + } + }, + ] + }) +} + +resource "aws_iam_policy" "lambda_logs" { + name = "${local.resource_prefix}-lambda-logs" + description = "Allows Lambda function to write logs to CloudWatch" + + policy = <