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.


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

Similar Posts You Might Enjoy

NetApp DataSense on AWS

Over the last years, demands and expectations on data security have increased dramatically. The main drivers are local data privacy regulations like the EU-GDPR, which imply awareness of sensitive data and an overview of potential risks. Amazon has offered its service Macie in 2017, added new capabilities lately, and is doing a great job with data on S3. But how do you include your EFS/FSx file shares and RDS databases to eliminate blind spots? Meet NetApp Cloud DataSense. - by Thomas Heinen

Testing Terraform with InSpec (Part 2)

In this post, we will set it all up for easy working in Visual Studio Code. Let’s start! - by Thomas Heinen

Testing Terraform with InSpec (Part 1)

While Infrastructure-as-Code slowly becomes omnipresent, many of the communicated advantages of the approach stay mostly unrealized. Sure, code style checks (linting) and even automated documentation get more common every month. But one of the cornerstones often gets ignore: testing. Let’s see which types of code testing are available and how to do it without writing too much code. The promise of the Infrastructure-as-Code (short: IaC) movement is to handle infrastructure just as if it was a program. - by Thomas Heinen