Skip to content
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

New attack technique: Usage of SSM StartSession on multiple instances #477

Merged
merged 8 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions docs/attack-techniques/AWS/aws.execution.ssm-start-session.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: Usage of ssm:StartSession on multiple instances
---

# Usage of ssm:StartSession on multiple instances

<span class="smallcaps w3-badge w3-orange w3-round w3-text-sand" title="This attack technique might be slow to warm up or detonate">slow</span>
<span class="smallcaps w3-badge w3-blue w3-round w3-text-white" title="This attack technique can be detonated multiple times">idempotent</span>

Platform: AWS

## MITRE ATT&CK Tactics


- Lateral Movement

## Description


Simulates an attacker utilizing AWS Systems Manager (SSM) StartSession to gain unauthorized interactive access to multiple EC2 instances.

<span style="font-variant: small-caps;">Warm-up</span>:

- Create multiple EC2 instances and a VPC (takes a few minutes).

<span style="font-variant: small-caps;">Detonation</span>:

- Initiates a connection to the EC2 for a Session Manager session.

References:

- https://hackingthe.cloud/aws/post_exploitation/run_shell_commands_on_ec2/#session-manager
- https://awstip.com/responding-to-an-attack-in-aws-9048a1a551ac


## Instructions

```bash title="Detonate with Stratus Red Team"
stratus detonate aws.execution.ssm-start-session
```
## Detection


Identify, through CloudTrail's <code>StartSession</code> event, when a user is starting an interactive session to multiple EC2 instances. Sample event:

```
{
"eventSource": "ssm.amazonaws.com",
"eventName": "StartSession",
"requestParameters": {
"target": "i-123456"
},
"responseElements": {
"sessionId": "...",
"tokenValue": "Value hidden due to security reasons.",
"streamUrl": "wss://ssmmessages.eu-west-1.amazonaws.com/v1/data-channel/..."
},
}
```


2 changes: 2 additions & 0 deletions docs/attack-techniques/AWS/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT

## Lateral Movement

- [Usage of ssm:StartSession on multiple instances](./aws.execution.ssm-start-session.md)

- [Usage of EC2 Instance Connect on multiple instances](./aws.lateral-movement.ec2-instance-connect.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 @@ -25,6 +25,7 @@ This page contains the list of all Stratus Attack Techniques.
| [Download EC2 Instance User Data](./AWS/aws.discovery.ec2-download-user-data.md) | [AWS](./AWS/index.md) | Discovery |
| [Launch Unusual EC2 instances](./AWS/aws.execution.ec2-launch-unusual-instances.md) | [AWS](./AWS/index.md) | Execution |
| [Execute Commands on EC2 Instance via User Data](./AWS/aws.execution.ec2-user-data.md) | [AWS](./AWS/index.md) | Execution, Privilege Escalation |
| [Usage of ssm:StartSession on multiple instances](./AWS/aws.execution.ssm-start-session.md) | [AWS](./AWS/index.md) | Lateral Movement |
| [Open Ingress Port 22 on a Security Group](./AWS/aws.exfiltration.ec2-security-group-open-port-22-ingress.md) | [AWS](./AWS/index.md) | Exfiltration |
| [Exfiltrate an AMI by Sharing It](./AWS/aws.exfiltration.ec2-share-ami.md) | [AWS](./AWS/index.md) | Exfiltration |
| [Exfiltrate EBS Snapshot by Sharing It](./AWS/aws.exfiltration.ec2-share-ebs-snapshot.md) | [AWS](./AWS/index.md) | Exfiltration |
Expand Down
7 changes: 7 additions & 0 deletions docs/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ AWS:
platform: AWS
isIdempotent: true
Lateral Movement:
- id: aws.execution.ssm-start-session
name: Usage of ssm:StartSession on multiple instances
isSlow: true
mitreAttackTactics:
- Lateral Movement
platform: AWS
isIdempotent: true
- id: aws.lateral-movement.ec2-instance-connect
name: Usage of EC2 Instance Connect on multiple instances
isSlow: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package aws

import (
"context"
_ "embed"
"fmt"
"github.com/aws/aws-sdk-go-v2/service/ssm"
"github.com/datadog/stratus-red-team/v2/pkg/stratus"
"github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack"
"strings"
)

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

func init() {
const codeBlock = "```"
stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{
ID: "aws.execution.ssm-start-session",
FriendlyName: "Usage of ssm:StartSession on multiple instances",
IsSlow: true,
Description: `
Simulates an attacker utilizing AWS Systems Manager (SSM) StartSession to gain unauthorized interactive access to multiple EC2 instances.

Warm-up:

- Create multiple EC2 instances and a VPC (takes a few minutes).

Detonation:

- Initiates a connection to the EC2 for a Session Manager session.

References:

- https://awstip.com/responding-to-an-attack-in-aws-9048a1a551ac (evidence of usage in the wild)
- https://hackingthe.cloud/aws/post_exploitation/run_shell_commands_on_ec2/#session-manager
`,
Detection: `
Identify, through CloudTrail's <code>StartSession</code> event, when a user is starting an interactive session to multiple EC2 instances. Sample event:

` + codeBlock + `
{
"eventSource": "ssm.amazonaws.com",
"eventName": "StartSession",
"requestParameters": {
"target": "i-123456"
},
"responseElements": {
"sessionId": "...",
"tokenValue": "Value hidden due to security reasons.",
"streamUrl": "wss://ssmmessages.eu-west-1.amazonaws.com/v1/data-channel/..."
},
}
` + codeBlock + `
`,
Platform: stratus.AWS,
PrerequisitesTerraformCode: tf,
IsIdempotent: true,
MitreAttackTactics: []mitreattack.Tactic{mitreattack.Execution},
Detonate: detonate,
})
}

func detonate(params map[string]string, providers stratus.CloudProviders) error {
ssmClient := ssm.NewFromConfig(providers.AWS().GetConnection())
instanceIDs := strings.Split(params["instance_ids"], ",")

for _, instanceID := range instanceIDs {
cleanInstanceID := strings.Trim(instanceID, " \"\n\r")
_, err := ssmClient.StartSession(context.Background(), &ssm.StartSessionInput{
christophetd marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you try this? I'm not able to make it work:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to reproduce a 501 InternalFailure (I'm using the same AWS region) but I was able to reproduce a 400 TargetNotConnected when the StartSession happens before the SSM agent is running. Because of this, I added a retry mechanism that waits for 10 seconds before trying again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 1a2c871

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

output now:

2024/02/09 11:53:06 Checking your authentication against AWS
2024/02/09 11:53:07 Note: This is a slow attack technique, it might take a long time to warm up or detonate
2024/02/09 11:53:07 Warming up aws.execution.ssm-start-session
2024/02/09 11:53:07 Initializing Terraform to spin up technique prerequisites
2024/02/09 11:53:24 Applying Terraform to spin up technique prerequisites
2024/02/09 11:55:23 Instances ready:
  i-07345b85bfc1b1e81 in eu-west-1a
  i-0793addc3e1967502 in eu-west-1a
  i-058972b50511cb498 in eu-west-1a
2024/02/09 11:55:23 Waiting for 3 instances to show up in AWS SSM. This can take a few minutes.
2024/02/09 11:55:42 Instances are ready and registered in SSM!
2024/02/09 11:55:42 Starting SSM sessions on each instance...
Session started on instance i-07345b85bfc1b1e81
Session started on instance i-0793addc3e1967502
Session started on instance i-058972b50511cb498

Target: &cleanInstanceID,
})

if err != nil {
return fmt.Errorf("failed to start session with instance %s: %v", cleanInstanceID, err)
}

fmt.Printf("Session started with instance %s\n", cleanInstanceID)
}

return nil
}
129 changes: 129 additions & 0 deletions v2/internal/attacktechniques/aws/execution/ssm-start-session/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}

provider "aws" {
skip_region_validation = true
skip_credentials_validation = true
default_tags {
tags = {
StratusRedTeam = true
}
}
}

locals {
resource_prefix = "stratus-red-team-ssm-start-session-lateral-movement"
}

variable "instance_count" {
description = "Number of instances to create"
default = 3
}

data "aws_availability_zones" "available" {
state = "available"
}

module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0"

name = "${local.resource_prefix}-vpc"
cidr = "10.0.0.0/16"

azs = [data.aws_availability_zones.available.names[0]]
private_subnets = ["10.0.1.0/24"]
public_subnets = ["10.0.128.0/24"]

map_public_ip_on_launch = false
enable_nat_gateway = true

tags = {
StratusRedTeam = true
}
}

data "aws_ami" "amazon-2" {
most_recent = true

filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-ebs"]
}
owners = ["amazon"]
}

resource "aws_network_interface" "iface" {
count = var.instance_count
subnet_id = module.vpc.private_subnets[0]

private_ips = [format("10.0.1.%d", count.index + 10)]
}

resource "aws_iam_role" "instance-role" {
name = "${local.resource_prefix}-role"
path = "/"

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_iam_role_policy_attachment" "rolepolicy" {
role = aws_iam_role.instance-role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

resource "aws_iam_instance_profile" "instance" {
name = "${local.resource_prefix}-instance"
role = aws_iam_role.instance-role.name
}

resource "aws_instance" "instance" {
count = var.instance_count
ami = data.aws_ami.amazon-2.id
instance_type = "t3.micro"
iam_instance_profile = aws_iam_instance_profile.instance.name

network_interface {
device_index = 0
network_interface_id = aws_network_interface.iface[count.index].id
}

tags = {
Name = "${local.resource_prefix}-instance-${count.index}"
}
}

output "instance_ids" {
value = aws_instance.instance[*].id
}

output "display" {
value = format("Instances ready: \n%s", join("\n", [
for i in aws_instance.instance :
format(" %s in %s", i.id, data.aws_availability_zones.available.names[0])
]))
}

output "instance_role_name" {
value = aws_iam_role.instance-role.name
}
1 change: 1 addition & 0 deletions v2/internal/attacktechniques/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/discovery/ec2-get-user-data"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/execution/ec2-launch-unusual-instances"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/execution/ec2-user-data"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/execution/ssm-start-session"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/exfiltration/ec2-security-group-open-port-22-ingress"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/exfiltration/ec2-share-ami"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/aws/exfiltration/ec2-share-ebs-snapshot"
Expand Down
Loading