Role Abuse: SSM
This page describes how a compromised machine with the default AmazonSSMRoleForInstancesQuickSetup role can allow an attacker to move laterally to all other machines holding this role in the VPC.
In this article, we will explore an interesting attack path in AWS that we encountered in the past: The Amazon Systems Manager. This solution allows centralized management of cloud and on-premise resources. It can by activated for an EC2 instance by assigning a role to the endpoint. However, the default instance role assignment, AmazonSSMRoleForInstancesQuickSetup, has an interesting side-effect: Instances with this role can execute commands or start sessions on each other.
We will attempt to move laterally from the compromised ACTIVEMQ EC2 instance with the AmazonSSMRoleForInstancesQuickSetup role to the DOTNETNUKE machine, which also holds this role. This article uses Cobalt Strike. However, any C2 framework could do, given some creativity.
Attack scenario overview
We start the jouney on the compromised ACTIVEMQ EC2 instance, where we have a Cobalt Strike session. We will use the Curl BOF from Alfie Champion's BOF collection to send an HTTP request to the internal metadata API in AWS.
Cobalt Strike Curl BOF to contact the internal metadata API
This results in an HTTP response, indicating that this machine holds the AmazonSSMRoleForInstancesQuickSetup role.
Result showing AmazonSSMRoleForInstancesQuickSetup
Next, we request AWS credentials for this role.
Requesting credentials for the role
The response comes back with an AccessKeyId, SecretAccessKey and Token value (redacted). This means that we can now impersonate the compromised instance in the context of the AmazonSSMRoleForInstancesQuickSetup role.
Obtained AWS Credentials for the role
The newly obtained credentials can be used to interact with the AWS APIs programatically, or we can use Rhinosecuritylabs' pacu tool to generate a console link for our convenience. The first step is to create a ~/.aws/credentials file with the credentials:
aws_access_key_id=<insert AccessKeyId value>
aws_secret_access_key=<insert SecretAccessKey value>
aws_session_token=<insert Token value>
Next, pacu can be launched via docker, while mounting the AWS credentials in the container.
docker run -it -v ~/.aws:/root/.aws rhinosecuritylabs/pacu:latest
Next, we can import the AWS credentials and validate our role through the AWS console CLI.
aws sts get-caller-identity
Imported the keys and validated the assumed role
Finally, pacu can generate the console login link to authenticate via a web browser via the following command:
Pacu generated a (redacted) console link
Browsing the URL automagically authenticates as the compromised instance with the AmazonSSMRoleForInstancesQuickSetup role.
AWS Console access as the compromised ACTIVEMQ instance with the AmazonSSMRoleForInstancesQuickSetup role
At this point, our role allows us to access the the AWS System Manager via the AWS Console. This service has (at least) two interesting features under Node Management: Session Manager and Run Command.
Run Command allows to run individual commands. For example, imagine a scenario where 30 Linux machines in the AWS VPC have the AmazonSSMRoleForInstancesQuickSetup. Machine 1 has an application running with an SSRF vulnerability, allowing an attacker to request AWS credentials from the internal metadata API and asume the role. He could use this interact with the AWS API to run a command to download and run a Command and Control agent on all 29 other machines.
We will focus on the manual approach via the Session Manager, which allows starting PowerShell and other sessions on the other machines with the default SSM role. The first step is to browse the AWS console and start a new session in the Session Manager.
Since we already compromised ACTIVEMQ, we will start a session on the only other available machine, DOTNETNUKE.
This drops us in a PowerShell session as the privileged ssm-user, where we first perform a trivial AMSI bypass (copy and edit a payload from amsi.fail) and then download and execute a stageless PowerShell beacon in-memory.
AMSI bypass and beacon launch from PowerShell
This results in an active Cobalt Strike C2 connection on DOTNETNUKE as the ssm-user from powershell.exe.
Beacon from DOTNETNUKE
In this article, we explored how the default Amazon Systems Manager role of one compromised machine can be abused to move laterally to other instances holding the same role.