Skip to content

Commit

Permalink
Exfiltration of EBS snapshots and AMIs: Handle error when EBS encrypt…
Browse files Browse the repository at this point in the history
…ion by default is enabled (closes #109)
  • Loading branch information
christophetd committed Mar 31, 2022
1 parent 44c83db commit 2855978
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/datadog/stratus-red-team/internal/providers"
"github.com/datadog/stratus-red-team/internal/utils"
"github.com/datadog/stratus-red-team/pkg/stratus"
"github.com/datadog/stratus-red-team/pkg/stratus/mitreattack"
"log"
Expand Down Expand Up @@ -73,6 +74,13 @@ func detonate(params map[string]string) error {
},
})

if err != nil && utils.IsErrorDueToEBSEncryptionByDefault(err) {
log.Println("Note: Stratus detonated the attack, but the sharing was unsuccessful. " +
"This is likely because EBS default encryption is enabled in the region. " +
"Nonetheless, it did simulate a plausible attacker action.")
return nil
}

if err != nil {
return errors.New("Unable to share AMI with external AWS account: " + err.Error())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/datadog/stratus-red-team/internal/providers"
"github.com/datadog/stratus-red-team/internal/utils"
"github.com/datadog/stratus-red-team/pkg/stratus"
"github.com/datadog/stratus-red-team/pkg/stratus/mitreattack"
"log"
Expand Down Expand Up @@ -73,6 +74,14 @@ func detonate(params map[string]string) error {
Add: []types.CreateVolumePermission{{UserId: &ShareWithAccountId}},
},
})

if err != nil && utils.IsErrorDueToEBSEncryptionByDefault(err) {
log.Println("Note: Stratus detonated the attack, but the sharing was unsuccessful. " +
"This is likely because EBS default encryption is enabled in the region. " +
"Nonetheless, it did simulate a plausible attacker action.")
return nil
}

return err
}

Expand Down
23 changes: 23 additions & 0 deletions internal/utils/aws_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/sts"
"log"
"strings"
)

func GetCurrentAccountId(cfg aws.Config) (string, error) {
Expand All @@ -29,3 +30,25 @@ func AwsConfigFromCredentials(accessKeyId string, secretAccessKey string, sessio

return cfg
}

func IsErrorDueToEBSEncryptionByDefault(err error) bool {
if err == nil {
return false
}
errorMessage := strings.ToLower(err.Error())

// EBS snapshots
// error: operation error EC2: ModifySnapshotAttribute, https response error StatusCode: 400, RequestID: 12f44aeb-7b3b-4488-ac46-a432d20cc7a9, api error OperationNotPermitted: Encrypted snapshots with EBS default key cannot be shared
if strings.Contains(errorMessage, "operationnotpermitted") && strings.Contains(errorMessage, "ebs default key") {
return true
}

// AMIs
// error: operation error EC2: ModifyImageAttribute, https response error StatusCode: 400, RequestID: 85f85eff-4114-4861-a659-f9aeea48d78b, api error InvalidParameter: Snapshots encrypted with the AWS Managed CMK can't be shared. Specify another snapshot.
if strings.Contains(errorMessage, "invalidparameter") && strings.Contains(errorMessage, "snapshots encrypted with the aws managed cmk") {
return true
}

return false

}
20 changes: 20 additions & 0 deletions internal/utils/aws_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package utils

import (
"errors"
"github.com/aws/aws-sdk-go-v2/service/cloudtrail/types"
"github.com/stretchr/testify/assert"
"testing"
)

func TestIsErrorRelatedToEbsEncryptionByDefault(t *testing.T) {
assert.False(t, IsErrorDueToEBSEncryptionByDefault(nil))
assert.False(t, IsErrorDueToEBSEncryptionByDefault(errors.New("foo")))
assert.False(t, IsErrorDueToEBSEncryptionByDefault(&types.OperationNotPermittedException{}))
assert.True(t, IsErrorDueToEBSEncryptionByDefault(
errors.New("operation error EC2: ModifySnapshotAttribute, https response error StatusCode: 400, RequestID: 12f44aeb-7b3b-4488-ac46-a432d20cc7a9, api error OperationNotPermitted: Encrypted snapshots with EBS default key cannot be shared"),
))
assert.True(t, IsErrorDueToEBSEncryptionByDefault(
errors.New("operation error EC2: ModifyImageAttribute, https response error StatusCode: 400, RequestID: 85f85eff-4114-4861-a659-f9aeea48d78b, api error InvalidParameter: Snapshots encrypted with the AWS Managed CMK can't be shared. Specify another snapshot"),
))
}

0 comments on commit 2855978

Please sign in to comment.