Sep 23, 2021
After about two hours, the scan of Acme Inc.’s web site was almost complete. Adriana hadn’t found anything and was about to give up when all of a sudden: Access Denied! With a little digging, she found a URL with “newtest” in it. It appeared to be a test for a new page. Interesting, she thought, the change language referred to a local file, could this be something? Yes! Trying 169.254.169.254 succeeded and she managed to extract AWS credentials. She looked to see if any of the credential’s permissions were useful to her. Most of them had low permission access, but then she noticed something interesting… a “role” with a policy attached named “devops_stuff_do_not_delete”. She examined this role more closely. Yes, an admin role that can be assumed by anyone. Jackpot!!
This type of identity and access management (IAM) risk is very real. While debugging an issue DevOps allows admin permissions for their testing. Then an attacker finds a forgotten unpatched vulnerability (in this example a server-side request forgery vulnerability) that allows her to compromise an instance and get credentials. The attacker then uses these credentials to use the DevOps role with the permissive policy and — the breach occurs.
Note: 169.254.169.254 is used in Amazon EC2 and other cloud computing platforms to distribute metadata to cloud instances.
To understand how this IAM cyber attack scenario played out, let’s start with a simple explanation of how AWS Identity and Access Management works. We can break IAM policies into three main components:
Note: AWS best practices endorse a fourth component known as conditioning, which allows creation of a pre-condition that must be met before permissions are granted. For example, only allowing requests from a certain account or user.
Now let’s suppose a cyber attacker found a website that’s running an unpatched application containing a common server-side request forgery (SSRF) vulnerability. An SSRF vulnerability can allow an attacker to induce a server-side application to make HTTP requests to an arbitrary domain of the attacker’s choosing, e.g., the web URL http://coolwebsite.com/url?eng.php. Under normal circumstances, the website will provide the english page via eng.php. However, if an attacker changes the eng.php filename to point to a different path, such as a website, the web server will dutifully carry out this request. Now if the target of the request is an internal resource (like the instance metadata server) it will respond since the origin of the request comes from an internal source. For more details on this vulnerability see the article : Steal EC2 Metadata Credentials via SSRF.
To fully appreciate the example above, we need to learn a little more about AWS IAM roles. In AWS, user identities are provided with an authentication token. But what if you wanted to grant a third-party service or tool access to your environment, or maybe an application like the above web server? It would not be easy to create and maintain a user for each service/app/vendor. AWS thought about this issue and provided a solution named IAM role. A role does not have username/password or access key. A role is a standalone identity with no explicit user. Think of it as a boarding pass for an account or resource. This boarding pass is pre-granted with specific permissions (or all permissions) to be used against a specific service (or all services). Roles can be assumed by users, other roles, AWS services, or an entire account (all users from that account), and doing so grants the one who assumes it the permissions and resource it has.
Back to Adriana, our hacker. She used the role she found in the instance via an SSRF vulnerability and figured out that this role does not provide much, but she also found one very simple and important permission that this role DOES have, which is the ability to assume another role. The identity that wishes to assume the role needs to have permissions to do so, meaning that our web server instance (in this example) was granted permissions to assume the role that was found in the instance metadata. This role also had its own permissions to assume another role. Looking around, our attacker found there was a role with pre-granted permissions (policy) that had a very interesting name (“devops_stuff_do_not_delete”). Trying to assume the role succeeded since the role from the web server (now used by our hacker) was allowed to assume this DevOps role AND the DevOps role was allowed to be assumed by anyone. In this example, the DevOps role had very extensive permissions that gave our hacker full permissions to the account.
We can now break down this cyber attack vector into the following parts:
This specific attack vector was very fruitful for Adriana. IAM configuration can be very complex, and misconfigurations occur when best practices are not followed. IAM misconfigurations also provide a lot more possibilities for attackers to use privilege escalation attack vectors. For example, when an IAM role is assumed by an identity, this identity can be an external identity. This means a user or a role that is not part of the same account as the service can use this role for access to the account based on the role permissions. Stay tuned and follow for Part 2 of our AWS IAM tech series by Orca for more information on account trust in the wild.
In Orca’s security research team, we encounter many IAM misconfigurations, most of the time they are made by the lack of a complex IAM schema or just by human error (like when a QA engineer needs a “role” to conduct a time sensitive test and puts a * in the resource and then forgets to clean it up later). Good IAM hygiene means following the least privilege approach and cleaning up roles/users/groups and permissions no longer needed or never used. Let’s look at some examples of common misconfigurations we encounter daily at Orca.
Now let’s look at what happened after our attacker took control of the “golden role.” She probably searched for some crown jewels. Most organizations have sensitive information that attackers seek, like databases, private repositories, documents, emails, etc. Some are protected using the Service Control Policies IAM mechanism and some are protected by other means, like private keys, passwords, networking boundaries (like security groups and ACLs). Either way, once an attacker finds a way to move laterally in the account, it’s just a matter of time (and some luck) until your most sensitive information finds itself magically outside your organization.
To avoid the above scenario, DevOps teams need to be able to catch IAM misconfigurations and lateral movement opportunities before an attacker. This is unlikely to happen if you’re using a cloud security posture management (CSPM) solution, which focuses only on control plane data. By only looking at the data that comes from the cloud provider’s API (and not workload data), one might miss authentication keys saved on local assets, misconfigurations on servers, secrets hidden in plain sight like in documents, notes, scripts, environment variables, and so on.
The answer is to use something Gartner calls a cloud native application protection platform (CNAPP), like Orca. A CNAPP looks at both the cloud infrastructure plane and workloads to give you a complete picture of both. Thus, Orca finds secrets, IAM misconfigurations, and vulnerabilities on the cloud infrastructure plane AND on workloads. And with its agentless approach, Orca has you 100% covered by scanning every workload with no gaps in coverage so you can work at DevOps speed.