Map out your IAM with PMapper
Writing “Least Privilege” policies is an art in itself, but it inevitably leads to a large number of JSON-based policies in your accounts. As one of the rules of good security is “low maintainability = low security”, let’s dive into tools which can show us risks inside our policies - which might even result in paths to administrative privileges!
You might be familiar with the following situation: An organization owns dozens of AWS accounts, for shared services, dev/test and production environments. Between all those accounts there are cross account roles which people can use to get privileges with. As you created all your policies as least privilege as possible, you have hundreds of policies and maintain a secure environment.
Are you really?
A while ago I was working on an AWS security review for a customer in exactly that situation. Reading all those JSON policies made my head hurt and things seemed pretty cool. Until I found something - developers were allowed to attach existing roles to Lambda functions. One of the allowed roles allowed to create new IAM policies. And as developer are developers, they could update code of Lambda functions as well.
Basically, a developer could change a Lambda, use that existing role with it, create a new administrative policy and thus had indirect administrative privileges. And probably nobody knew that, because this environment was so segmented that you did not have any idea which combinations might lurk in its policies.
Just recently, I came across a tool which would have made my task back then much easier. PMapper (short for Principal Mapper can map IAM entities and check for toxic combinations.
PMapper
This tool was written by NCC Group, an IT security company from the UK. It will download all users, roles, groups and policies from one or multiple AWS accounts and then allow visualization and interactive queries:
$ pmapper graph create
2021-08-16 22:16:25+0200 | Obtaining IAM Users/Roles/Groups/Policies in the account.
2021-08-16 22:16:39+0200 | Sorting users, roles, groups, policies, and their relationships.
2021-08-16 22:16:39+0200 | Obtaining Access Keys data for IAM users
2021-08-16 22:16:39+0200 | Gathering MFA virtual device information
2021-08-16 22:16:40+0200 | Gathering MFA physical device information
2021-08-16 22:16:40+0200 | Determining which principals have administrative privileges
2021-08-16 22:16:41+0200 | Initiating edge checks.
2021-08-16 22:16:41+0200 | Generating Edges based on EC2 Auto Scaling.
...
Graph Data for Account: 123456789012
# of Nodes: 153 (37 admins)
# of Edges: 303
# of Groups: 4
# of (tracked) Policies: 246
This is only from a personal playground account, and not even close to the accounts I have seen. You can see there are a lot of policies and nodes (IAM entities) already.
The key to this tool is the use of graph relationships. Which Instance has which Profile attached, which Policies are included in that one, and so on. You can create a visualization of all these relationships, which is impressive but probably not very useful on large accounts. But there is also an option to only graph the possible privilege escalations (how an entity can extend its privileges):
$ pmapper visualize --only-privesc --image privesc.jpg
Even more useful is the possibility to run interactive queries on the resulting graph database
$ pmapper query 'who can do s3:PutObject'
role/AllowAllRole IS authorized to call action s3:PutObject for resource *
...
role/aws-ec2-spot-fleet-tagging-role CAN call action s3:PutObject for resource * THRU role/DemoRole
role/aws-ec2-spot-fleet-tagging-role can use EC2 to run an instance with an existing instance profile to access role/DemoRole
role/DemoRole IS authorized to call action s3:PutObject for resource *
...
Seems like I need to clean up my account here? But you can clearly see that the tool found out which roles can be assumes by another one and has access to the action (or even a specified bucket).
If you do not want to manually dig through all possibilities, use the analysis function:
$ pmapper analysis --output json
{
"account": "123456789012",
"date_and_time": "2021-08-16T22:52:26.708904+02:00",
"findings": [
{
"title": "IAM Principals Can Escalate Privileges",
"severity": "High",
"impact": "A lower-privilege IAM User or Role is able to gain administrative privileges. This could lead to the lower-privilege principal being used to compromise the account and its resources.",
"description": "In AWS, IAM Principals such as IAM Users or IAM Roles have their permissions defined using IAM Policies. These policies describe different actions, resources, and conditions where ...",
"recommendation": "Review the IAM Policies that are applicable to the affected IAM User(s) or Role(s). Either reduce the permissions of the administrative principal(s), or reduce the permissions of the principal(s) that can access the administrative principals."
},
{
"title": "IAM Users With Administrative Permissions But No MFA Device",
"severity": "Medium",
"impact": "If an attacker gains access to any of the noted sensitive IAM Users, there is no secondary layer of protection in place to prevent the AWS from being compromised.",
"description": "In AWS, an IAM User can be assigned a device for Multi-Factor Authentication (MFA). When an IAM User is assigned an MFA device, they are required to provide an extra factor of ...",
"recommendation": "Assign an MFA device to each of the noted IAM Users."
},
...
]
}
You can seen that the findings are categorized and even sorted by severity. Additionally, some clear text description can be used to explain the impact of the finding.
Storing Data in a Specific Folder
By default, PMapper uses ~/.local/share/principalmapper
on Linux to store all scan results. If you want to put the raw data into another folder, for example to keep results next to your findings, you can can specify the desired location via an environment variable:
PMAPPER_STORAGE=/home/user/scan-results pmapper graph create