dAWShund – framework to put a leash on naughty AWS permissions
April 11, 2025
Nikolas Mantas
We did some interesting research focused on the AWS cloud platform that offers highly-permissive tools for security operations, such as incident response, auditing, inventorying, etc. These tools’ usage is typically considered legitimate and is rarely monitored, so they could be used against blue teams if fallen into the wrong hand. Laziness (the consulting term is “low-hanging fruit”) can be a great motive for attackers, especially when they can make an impact that matters with little knowledge and few resources…

We are happy to introduce the result of our research: dAWShund is a homemade Python 3 framework to help blue and red teams find resources in AWS, evaluate their access levels and visualize the relationships between them. Any memorable franchise needs a good trilogy, so our love for food and puns makes us split the tasks into three tools:

  • sAWSage: a modular script to enumerate AWS policies and resources across your target regions.
  • Gerakina (female falcon in Greek): if you have indulged in Greek nightlife, then you have spotted several food trucks (named kantines) around Athens. Nothing beats a good burger or hotdog after a long night out. The Gerakina script uses the consolidated output from sAWSage to evaluate the effective permissions between resources.
  • dAWShund: A fancy dish deserves a fancy presentation. This script visualizes the relationships between resources using graphs for easier ingestion into BloodHound, the famous Six Degrees of Domain Admin tool.

Figure 1 – our framework in a nutshell.

You can access the framework on FalconForce’s Github: https://github.com/FalconForceTeam/dAWShund.

Introduction

When digging into AWS, we found IAM Policy Simulator, a tool that helps administrators test their policies against their own organization; without actually enforcing them and the risk of breaking relationships and functionality.

Figure 2 – Policy Simulation usage from TinkyWinky user. It seems this Teletubby has been naughty…

Although promising at first glance, IAM Policy Simulator does not offer automation capabilities and is limited to one identity assessment per request. Looking under the hood, we found the responsible API “SimulatePrincipalPolicy” offers more parameter options than the limited GUI of IAM Policy Simulator. Interestingly enough, threat actors are aware of these capabilities, as its usage has been observed in wild. Fascinating details about how this API fits in the attack lifecycle are described in this blogpost.

The potential of the above-mentioned API sparked a year-long research on AWS built-in tools that lead to the development of dAWShund.

Some knife sharpening first

AWS terminology

Typically, everything in AWS can be considered a resource, as all resources created by IAM and services are assigned an ARN (Amazon Resource Name). For simplicity reasons, all IAM resources (Users, Groups, Roles) are called principals and the resources within services are called resources. A role is a better fitting principal to control access within AWS for a limited time (think of it as a Just-Enough-Access identity).

As you can imagine, AWS terminology confused us a lot during this time. It would be a shame not to share our artistic side in this blog, as we made doodle notes along the way to simplify and visualize the complicated, yet exciting relationships defined by AWS.

Policies

Before starting chopping onions, we should first learn the purpose of a recipe, where to get our ingredients and what tools we need. IAM is more than a fancy word in the cloud world, so our journey will begin by describing how AWS principals access services and their resources.

A principal without a policy is like a chef without access card to his restaurant. You can cook a great ravioli or make the best smash burger in town, but you still need access to the kitchen. AWS goes beyond this concept by defining in the same policy document, the expected behavior a chef (principal) within their kitchen workspace (resource) like allowing 15 minutes break or denying smoking near propane (actions).

Figure 3 – a principal without a policy cannot perform any action on any resource within AWS.

Figure 4 – a principal with attached policy can access a resource through explicitly defined actions.

Overall, a policy is a JSON document that defines permissions on a resource: who has access and what actions are allowed within AWS.

Service resources introduce a two-way authorization concept to give a granular access control. To access a resource, the principal and resource policy must have an EXPLICIT ALLOW effect describing the actions permitted within the resource. The complete list of services that support such policies is listed in the documentation. Imagine swiping your access card (Identity-based Policy) to access the restaurant’s front door, then using a fingerprint scanner on the security door (Resource-based Policy) before accessing the secret recipe (data) within the vault (service).

Figure 5 – some services require explicit policy setup on their resources to allow access.

Policy types

A thorough lookup on documentation revealed a complex association between seven types of policies that control all access (i.e., network, federation, services, etc.) within AWS that can be shortly described:

Identity-based

They associate with IAM principals (user, group, or role). They are categorized into two sub-types

  • Inline: a one-to-one relationship policy with a single IAM principal created by the Customer (i.e., the end user according to AWS SLAs).
  • Managed: a standalone policy that can be assigned to several principals. It can be created and administered by either the Customer or AWS.

Resource-based

An inline policy that associates with resources from specific AWS services that work with IAM. As seen previously, to access a resource you need both Identity-based and Resource-based policy.

Permission boundaries

They use managed policies to set the maximum permissions that can be granted for IAM principals.

Organizations Service Control Policies (SCP)

They define the maximum permissions of Identity-based and Resource-based policies for IAM users and roles within accounts in an AWS Organization or organizational unit (OU).

Organizations Resource Control Policies (RCP)

They define the maximum permissions of resources across multiple AWS without updating the IAM policies attached to each resource.

Access Control Lists (ACL)

They control the access of principals from other accounts.

Session policies

They control the access of a temporary session of a role or federated user.

Searching for quality ingredients

So, where do we start looking for policies? What if we can enumerate the policies for a good percentage of the AWS infrastructure by making only a few requests? Managed policies (think of it as the central repository of IAM policies within AWS for easier management) can reveal a decent quantity of information (AWS accounts, federated principals, resources in other regions, tags, etc.) about identity and resource relationships — and potentially exploitable misconfigurations.

The collection of Resource-based policies is a nightmare to automate. Some services (like Amazon SQS and SNS) save their policies in a slightly different format and require canonicalization when used together with other policy types. Additionally, Amazon’s love of warehousing everything in regions, impacts the time of enumeration of resources. Although it could be used as a detection opportunity for defenders, it also tests the patience of threat actors (and auditors) to thoroughly find all resources across all potential regions…

We had to doodle our way out this mess and focus only on the two policy types needed to understand what is inside an AWS infrastructure: Identity-based and Resource-based Policies. How all these components work together could be part of a larger scale research or auditing. After all, dAWShund got its concept by quick and casual dining, not a six-course meal experience in a fancy restaurant. However, haute cuisine influenced its development. The latest culinary trend is deconstructed food, and we too broke down the core elements of policies. After all, cooking and coding are an intrinsic art form…

Figure 6 – visual breakdown of elements deconstruction during policy enumeration. Notice how the color scheme of AWS resembles a hotdog…

This color scheme depicts the different API families needed to collect all ingredients into a “master” policy document:

  • Red for the enumeration of IAM principals and their attached inline policies. As you can imagine, this is very time-consuming and detection-prone.
  • Orange for managed policy enumeration. Quick and dirty, to reveal a good percentage of the infrastructure. Some policies are managed exclusively by AWS and others cannot be attached to principals. Hence enumeration with proper filtering can be faster!
  • Green for resource enumeration and their attached policies. Extremely slow, as enumeration needs to be done in ALL regions for ALL services.

After understanding policy types and where to find them, it’s time to fetch them! Using the first tool in our arsenal sAWSage, we associate and normalize policies with their respective principals and resources to export them harmonically.

Along this more than one year journey, sAWSage was refactored four times to enrich our enumeration outreach with modules of interesting built-in tools, such as Credentials Report. Often left unsanitized after audits, it provides useful information on the usage of MFA, access keys, etc. that can be leveraged by administrators, but also be exploited by threat actors.

All this trouble for making a simple hot-dog was worth it! Once we have our “master” policy document enriched with supporting information, we can finally sit and enjoy our hard-prepped meal, right?

Standing the heat of permissions evaluation

AWS follows an interesting access validation process of the permissions described in the policy document. For each IAM principal making a request, all its associated policies are evaluated for the existence of a Deny action. If one exists, then the request is denied. Then AWS checks each statement of the policies for an Allow action. If at least one policy statement allows the action in the request, the request is allowed.

Figure 7 – evaluation flow from the official AWS documentation.

So, before taking a bite, we need to check these actions and evaluate their effective permissions. This is where you need Gerakina, the second tool of our framework. Gerakina gets the ingredients ingested from sAWSage (principals, resources, actions) to reveal their effective permissions and to bring joy to hungry blue and red teams. Using the SimulatePrincipalPolicy API, our tool leverages the AWS enforcement code to decide whether a request sent from a principal to a resource should be allowed or denied.

This permission evaluation could either be done by making requests directly to AWS using SimulatePrincipalPolicy (but at the risk of getting detected), or using offline tools like Policyuniverse (that might not always be up-to-date with the latest changes).

We decided to put our “trust anchor” in AWS for the evaluation of access rights using its native API for the following reasons:

  • To highlight the impact of APIs, such as SimulatePrincipalPolicy, when proper IAM policies are not enforced in principals. Forget using iam:* in your policies from now on…
  • A black box offering via the API deserves a black box approach. We would however revisit the topic should the code of the AWS evaluation flow, as shown in Figure 7, be publicly released to make the evaluation “offline”.
  • According to the documentation, the APIs covers cross-account and Organizations service control policies (SCP) effects simulation, which is great for situational awareness and future development!

As at the writing of this blog, the policy simulation results are an accurate representation of the ACTUAL policies set in our AWS test environment. Only the Allow effective permissions ingested to Gerakina from sAWSage are stored from the evaluated policies, not the Deny actions. We based our decision on the fact that our framework is not an audit tool and will never replace good old Excel in auditing. Hence, the focus should be on what actions could be exploited by attackers.

Putting a leash on naughty permissons

Finally, after enumerating our principals and resources and evaluating their permissions, dinner is served! Our third and final tool, dAWShund creates the nodes and edges between the allowed effective permissions and consolidates them into a neo4j database for ingestion and analysis into Bloodhound or Neo4j Browser.

Figure 8 – analysis from Neo4j Browser.

Your content goes here.

How to use the framework

The framework aims to be used in a serial way. First we enumerate the principals, resources and their respective polices with sawsage.py. You can specify the your target regions by providing a comma- separated list.

python sawsage.py --profile <aws_profile_name> [--region <aws_region_name> --cr]

If you feel extremely lucky (and naughty), try using –cr to gain a better visibility inside the infrastructure and download the Credentials Report.

Our ingredients from the enumeration will be exported on the enumeration folder. Stand in the line of our food truck Gerakina and get your permissions validated. Sit comfortably and wait while we contact AWS to create the relationships of resources.

python3 gerakina.py --profile <your_profile_name>

Finally, you can enjoy your hard-earned hot-dog and perform cypher queries in Neo4j or Bloodhound.

python3 dawshund.py --file effective_permissions.json

As a reference, you can use the following cypher queries to find relationships between your resources.

Find users with disabled MFA:

MATCH (u:User)
WHERE u.mfa_active = false
RETURN u

Find users with inactive access keys:

MATCH (u:User)
WHERE u.access_key_1_active = "false" AND u.access_key_2_active = "false"
RETURN u.arn

Find users with their password enabled, but never used:

MATCH (u:User)
WHERE u.password_enabled = true AND (u.password_last_used IS NULL OR u.password_last_used = "N/A")
RETURN u.arn

Users with expiring or non-rotating credentials:

MATCH (u:User)
WHERE u.password_next_rotation = "not_supported" OR u.access_key_1_last_rotated = "N/A"
RETURN u.arn

Find S3 buckets with overly permissive access (*)

MATCH (p)-[r]->(res:Resource)
WHERE r.Service = "s3" AND type(r) CONTAINS "*"
RETURN p.arn AS principal, type(r) AS action, res.arn AS resource

Find all principals with any access to the RDS service

MATCH (p)-[r]->(res:Resource)
WHERE r.Service = "rds"
RETURN labels(p)[0] AS type, p.arn AS principal, type(r) AS action, res.arn AS resource

For a complete walkthrough on setting up and using the framework, you can visit our GitHub page at: https://github.com/FalconForceTeam/dAWShund.

Closing thoughts

dAWShund has been in development for more than one year and was redesigned several times to extend its capabilities with newly found ingredients in this amazing recipe called AWS research. This is just the start! Our journey sparked several knowledge sharing sessions and opinion exchange between our blue and red team to shape it into a toolkit that can benefit our community. We had the chance to start the development through a series of questions, which only increased through time like graphs…

The framework was created within a blue team perspective. Hence, operational security is not adapted (yet). We still have to learn far more to become chefs, but hope to spark discussion within the community and shed light into effective permission validation. Federation and organizational trust are still an uncharted territory in the community and further research is required before extending our framework to become an all-go-to tool. We sincerely appreciate your feedback on our GitHub page for improvements and bug fixes. Our framework can greatly be improved from the experience of large AWS adopters and red teaming feedback.

Knowledge center

Other articles

Exploring WinRM plugins for lateral movement

Exploring WinRM plugins for lateral movement

[dsm_breadcrumbs show_home_icon="off" separator_icon="K||divi||400" admin_label="Supreme Breadcrumbs" _builder_version="4.18.0" _module_preset="default" items_font="||||||||" items_text_color="rgba(255,255,255,0.6)" custom_css_main_element="color:...

Together. Secure. Today.

Stay in the loop and sign up to our newsletter

FalconForce realizes ambitions by working closely with its customers in a methodical manner, improving their security in the digital domain.

Energieweg 3
3542 DZ Utrecht
The Netherlands

FalconForce B.V.
[email protected]
(+31) 85 044 93 34

KVK 76682307
BTW NL860745314B01