Background
AWS’s SSM Session Manager service is pretty nice. It allows for shell access to EC2 instances without needing to open up SSH ports to the world or configure security groups. All sessions are logged to Session Manager and you can restrict access to authorized groups of IAM users using policies.
Your EC2 instances may end up needing some ssm:
permissions, for example, the ones built into AmazonSSMManagedInstanceCore for communication with Fleet Manager, etc.
One might be tempted to allow all SSM commands via ssm:*
. This is a pretty bad idea.
The Problem
There are two problems here. First, we know already that Session Manager can both open shells into other instances, but has the additional feature of letting you choose the user that you connect as. Thankfully, root
is not allowed, but you can use this use this to access other user accounts on an EC2 instance.
Theoretically, you could use this to drop a backdoor in a web server by using access as apache
or nginx
.
If the instance also has EC2 permissions to list instances AND the ssm:StartSession
permission for them, it effectively grants an attacker the ability to log into any instance on your network.
Exploiting This
During one of the lab exercises for my Cybersecurity Master’s program, we were tasked with trying to elevate our privileges on a locked-down user on an EC2 instance. These instances (deployed via AWS’s Educate tool) had a custom policy enabled which allowed the instance to perform the ssm:StartSession
API call using the instance’s role.
Since I wasn’t able to install things, I hacked together a pure-Python implementation of the AWS session manager command line, which allowed me to log into another, more privileged user (for example, apache
).
This requires minimal packages (just python) and does not need root privileges to download and run as long as python and pip are installed. Since Python is pretty much universally available, and boto3
is commonly installed, this worked pretty well.
I used this to drop a suid/sgid binary as a backdoor to regain access as the target user without needing session manager. From there, my locked down user could execute the binary and get immediate access to things such as web server configuration, or other administrator accounts on the system.
Conclusion
Don’t give your EC2 instances more permissions than they need.
Avoid giving EC2 instances permissions such as ssm:StartSession
or ssm:RunCommand
. In a lot of cases, this is not necessary and opens up the possibility of an attacker moving laterally across your network, planting backdoors, etc.