Cognito, Ergo Some Extra Permissions

Leo Tsaousis (Senior Security Consultant · Reverse)

Cloud Village @ DEF CON 33 · Day 1 · Cloud Village

Overview

In his Cloud Village talk, "Cognito, Ergo Some Extra Permissions," Leo Tsaousis, a Senior Security Consultant at Reverse, unveiled a critical vulnerability within AWS CloudWatch Dashboards that, under specific circumstances, allowed unauthenticated users to gain unauthorized access to AWS account resources. The talk highlights a fundamental principle often overlooked: security monitoring solutions themselves can inadvertently introduce significant security risks. Tsaousis meticulously details how a combination of a "fail-open" logic bug in AWS Cognito Identity Pools and an oversight in how CloudWatch configured these pools led to the exposure of sensitive information, such as EC2 instance tags, and potentially even granted permissions to invoke Lambda functions.

Watch on YouTube

Visual summary for Cognito, Ergo Some Extra Permissions by Leo Tsaousis
Visual summary for Cognito, Ergo Some Extra Permissions by Leo Tsaousis

Key moments

  1. 0:00 CloudWatch dashboards: unauthenticated access security risk
  2. 2:30 How the CloudWatch vulnerability was discovered
  3. 3:50 Unexpected ec2:DescribeTags permission on dashboards
  4. 4:40 Cognito's role in unauthenticated CloudWatch access
  5. 6:00 Decoding shared dashboard's context parameter
  6. 6:50 Unauthorized operation: initial exploitation attempt fails

Cognito, Ergo Some Extra Permissions

Speakers: Leo Tsaousis, Senior Security Consultant, Reverse

Conference: Cloud Village

YouTube: https://www.youtube.com/watch?v=v4Zj7Qbkfy8

Overview

In his Cloud Village talk, "Cognito, Ergo Some Extra Permissions," Leo Tsaousis, a Senior Security Consultant at Reverse, unveiled a critical vulnerability within AWS CloudWatch Dashboards that, under specific circumstances, allowed unauthenticated users to gain unauthorized access to AWS account resources. The talk highlights a fundamental principle often overlooked: security monitoring solutions themselves can inadvertently introduce significant security risks. Tsaousis meticulously details how a combination of a "fail-open" logic bug in AWS Cognito Identity Pools and an oversight in how CloudWatch configured these pools led to the exposure of sensitive information, such as EC2 instance tags, and potentially even granted permissions to invoke Lambda functions.

The research began with a seemingly innocuous scanner alert about a publicly shared CloudWatch dashboard. This initial finding propelled Tsaousis into a deep investigation of AWS’s internal authentication mechanisms, particularly those involving Cognito. He uncovered that while AWS documentation provided warnings about permissions granted when sharing dashboards, the underlying implementation had a critical flaw. This flaw allowed an attacker, armed with nothing more than a dashboard’s public URL, to bypass intended security restrictions and assume the full permissions of the IAM role associated with the dashboard, rather than the scope-down policy enforced by Cognito’s "enhanced" authentication flow.

This article delves into the technical intricacies of Tsaousis's discovery, tracing the path from initial observation to full exploitation. It explores the role of Cognito Identity Pools, the distinction between "classic" and "enhanced" authentication flows, and the subtle configuration error that created a significant attack surface. Furthermore, it examines the potential impact, which escalated from merely listing EC2 tags to enabling "denial of wallet" attacks via Lambda invocation, and outlines the defensive implications for AWS users.

Background

▶ Watch: CloudWatch dashboards: unauthenticated access security risk (0:00)

The journey into this vulnerability began during a routine cloud security review. As part of an automated scanning phase, a tool flagged a CloudWatch dashboard as being publicly shared. While the scanner’s warning primarily focused on the general bad practice of exposing state information, Leo Tsaousis, the speaker, was intrigued by the potential for a deeper security impact beyond mere data visibility. His curiosity led him to the AWS documentation for CloudWatch dashboard sharing, which contained a subtle yet crucial warning: "The people you share the dashboard with are going to get some permissions into the account." Scrolling further, the documentation explicitly listed these permissions, including three CloudWatch-specific actions and, notably, ec2:DescribeTags.

The inclusion of ec2:DescribeTags immediately struck Tsaousis as an anomaly. While CloudWatch permissions made logical sense for viewing dashboard data, the ability to describe EC2 tags seemed extraneous for a dashboard viewer. This observation served as the initial pivot point for his research. He noted that when a CloudWatch dashboard is shared publicly, a unique URL is generated, containing a context parameter. This parameter, upon closer inspection, was found to be an encoded JSON object. Decoding it revealed several fields, including an identityPoolId (identified as I) and, critically, an IAM role ARN (identified as O).

The presence of an identityPoolId pointed directly to AWS Cognito Identity Pools, a service designed to grant temporary, limited-privilege credentials to users, including unauthenticated ones. This is a standard AWS mechanism for providing access to AWS resources from client-side applications without requiring full AWS credentials. Tsaousis observed that the client-side JavaScript of the CloudWatch dashboard made two key API calls to the Cognito Identity service: cognito-identity:GetId (to obtain an identity ID) and then cognito-identity:GetCredentialsForIdentity (to trade that identity ID for temporary AWS credentials).

However, when Tsaousis attempted to use these browser-obtained credentials to execute aws ec2 describe-tags via the AWS CLI, the operation failed with an "unauthorized operation" error. This unexpected denial of access, despite the documentation suggesting the permission should be granted, became the central mystery. It indicated that AWS Cognito was applying a scope-down policy – an inline session policy that was selectively removing certain permissions, specifically ec2:DescribeTags, from the granted credentials. This behavior is part of Cognito's "enhanced" authentication flow, designed to limit the effective permissions for security. The core question then became: could this scope-down policy be bypassed?

Key Findings

▶ Watch: Unexpected ec2:DescribeTags permission on dashboards (3:50)

The central discovery of Leo Tsaousis's research is a critical vulnerability stemming from a "fail-open" logic bug within AWS Cognito Identity Pools when provisioned by CloudWatch Dashboards. This flaw allowed unauthenticated attackers, possessing only the URL of a publicly shared CloudWatch dashboard, to obtain temporary AWS credentials with the full permissions of the dashboard’s underlying IAM role, bypassing Cognito’s intended security restrictions.

The core of the vulnerability lies in the allowClassicFlow parameter of the CreateIdentityPool API call. When CloudWatch creates a Cognito Identity Pool to support dashboard sharing, it was failing to explicitly set this boolean field. Due to a design decision within Cognito, leaving allowClassicFlow undefined defaults its behavior to true, effectively enabling the less secure "classic" authentication flow. This "fail-open" default proved to be critical.

In the standard "enhanced" authentication flow, Cognito automatically applies a session-scoping policy that limits the permissions granted. For CloudWatch dashboards, this policy specifically excluded ec2:DescribeTags, explaining why initial attempts to list tags with browser-obtained credentials failed. However, by exploiting the allowClassicFlow default, an attacker could manually initiate a "classic" authentication flow. This involved extracting the identityPoolId and the iamRoleArn directly from the dashboard’s public URL (context parameter) and then using sts:AssumeRoleWithWebIdentity to explicitly assume the IAM role. When the role is explicitly assumed this way, Cognito's session-scoping policy is bypassed, granting the attacker temporary credentials with the full, unmitigated permissions of the IAM role.

The immediate impact of this vulnerability was the ability for unauthenticated users to perform ec2:DescribeTags, revealing potentially sensitive metadata stored in EC2 instance tags. While AWS advises against storing sensitive data in tags, Tsaousis's experience in cloud security assessments confirmed that many organizations disregard this advice, often storing PII, contact details, or even plain-text credentials in tags.

More significantly, the impact could be escalated if the dashboard's IAM role had additional permissions. CloudWatch offers features like "log table widgets" and "custom widgets," which require users to grant extra permissions to the dashboard's IAM role. For custom widgets, users are advised to add lambda:InvokeFunction permissions. If an attacker could obtain credentials with lambda:InvokeFunction permissions, they could repeatedly invoke a target Lambda function, leading to a "denial of wallet" attack by incurring significant financial charges for the account owner.

Tsaousis demonstrated the widespread nature of this issue by finding over 20 publicly exposed CloudWatch dashboard URLs via simple Google dorks and an additional 10+ using URL scanning services. He provided examples like the EWN (Australian weather event monitoring) and Monzie (global scavenger hunt game) dashboards, illustrating real-world exposures (though he did not fully exploit these for ethical reasons).

AWS addressed this vulnerability by deploying a fix in September 2024, explicitly setting the allowClassicFlow field to false when CloudWatch creates Cognito Identity Pools. This prevents the classic flow bypass. However, Tsaousis noted that no CVE was assigned, and the fix was not mentioned in public security bulletins, potentially limiting awareness among affected clients. Furthermore, a residual risk remains: for dashboards shared via Username/Password or SSO, intended viewers can still obtain the full IAM role permissions because their authentication flow explicitly requests the role, bypassing any scope-down.

Technical Deep Dive

▶ Watch: Cognito's role in unauthenticated CloudWatch access (4:40)

The technical core of this vulnerability hinges on the interaction between AWS CloudWatch Dashboards, AWS Cognito Identity Pools, and AWS Security Token Service (STS), specifically concerning the handling of temporary credentials and session policies.

When a CloudWatch dashboard is shared, particularly publicly, the AWS console (or underlying SDKs) provisions a Cognito Identity Pool to manage access. The dashboard URL contains a context parameter, which is a base64-encoded JSON object. This context object is crucial as it contains the identityPoolId (denoted as I) and the iamRoleArn (denoted as O) associated with the dashboard's permissions.

The Intended "Enhanced" Authentication Flow

The standard, intended flow for a dashboard viewer operates as follows:

  1. Dashboard Access: An unauthenticated user accesses the dashboard URL.
  2. Client-Side Code: The browser loads JavaScript from an Amazon CDN.
  3. Get Identity: The JavaScript makes a cognito-identity:GetId API call to the Cognito Identity Service, using the identityPoolId extracted from the context parameter. This call returns an IdentityId.
  4. Get Credentials: Next, the JavaScript makes a cognito-identity:GetCredentialsForIdentity API call, providing the IdentityId. Cognito then returns temporary AWS credentials (access key, secret key, session token).
  5. Session-Scoping Policy: Crucially, during this GetCredentialsForIdentity call, Cognito applies an inline session policy to the returned credentials. This policy acts as a scope-down mechanism, restricting the effective permissions. In the context of CloudWatch dashboards, this session policy explicitly excluded ec2:DescribeTags, allowing only CloudWatch and Lambda-related actions (if configured). This is why Tsaousis's initial attempt to use browser-obtained credentials to list EC2 tags failed. The effective permissions are the intersection of the IAM role's policy, any resource-based policies, and this session-based policy.

The Exploitable "Classic" Authentication Flow

The vulnerability arises because the allowClassicFlow parameter in the Cognito Identity Pool configuration was left undefined by CloudWatch during its creation. Cognito, due to a historical design decision for backward compatibility, treats an undefined allowClassicFlow as true, effectively enabling the "classic" authentication flow. This allows an attacker to bypass the session-scoping policy.

The exploitation steps for an unauthenticated attacker are as follows:

  1. Extract Parameters: The attacker obtains the publicly shared CloudWatch dashboard URL and extracts the identityPoolId (e.g., us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) and the iamRoleArn (e.g., arn:aws:iam::123456789012:role/CloudWatchDashboardRole) from the context parameter.
  2. Get Identity: The attacker makes a cognito-identity:GetId API call using the extracted identityPoolId. This step is identical to the enhanced flow and returns an IdentityId.
  3. Assume Role with Web Identity: Instead of calling cognito-identity:GetCredentialsForIdentity, the attacker directly uses the IdentityId to call sts:AssumeRoleWithWebIdentity. This is the critical difference. In this call, the attacker explicitly specifies the iamRoleArn of the dashboard.
  4. Bypass Scope-Down: When sts:AssumeRoleWithWebIdentity is used with an explicitly specified IAM role, the session-scoping policy applied by Cognito in the "enhanced" flow is not applied. The resulting temporary credentials inherit the full, unmitigated permissions of the specified IAM role.
  5. Exploitation: With these credentials, the attacker can now successfully execute aws ec2 describe-tags or any other action permitted by the IAM role, including lambda:InvokeFunction if the role was configured for custom widgets.

Root Cause and Remediation

The root cause was a combination of:

  • Logic Bug in CloudWatch/SDKs: When CloudWatch provisioned the Cognito Identity Pool, the CreateIdentityPool API call did not explicitly set the allowClassicFlow field.
  • Fail-Open Condition in Cognito: Cognito's default behavior for an undefined allowClassicFlow was true, enabling the classic flow.

This specific issue was observed when CloudWatch used AWS SDKs to create these resources. In contrast, if a user created a Cognito Identity Pool directly via the AWS console or using Terraform, allowClassicFlow would default to false (in the console via a checkbox, and explicitly by Terraform), thus being secure by default.

AWS fixed this by modifying CloudWatch's internal calls to explicitly set allowClassicFlow to false when creating Cognito Identity Pools for dashboards, regardless of the sharing method. This ensures that only the enhanced, scoped-down flow is possible for publicly shared dashboards.

Remaining Risks for Authenticated Users

While the fix mitigated the unauthenticated bypass, Tsaousis highlighted a remaining risk for intended viewers of dashboards shared via Username/Password or SSO. In these scenarios, the browser's client-side code explicitly requests the iamRoleArn during the authentication process (e.g., through a JWT from a SAML provider). Because the IAM role is explicitly requested, the session-scoping policy is bypassed, and intended viewers still receive credentials with the full permissions of the dashboard’s IAM role. This means if the IAM role has ec2:DescribeTags or lambda:InvokeFunction, legitimate (but potentially over-privileged) viewers can still access these beyond the dashboard's intended functionality.

Demo / Proof of Concept

▶ Watch: Decoding shared dashboard's context parameter (6:00)

Leo Tsaousis demonstrated a clear, end-to-end Proof of Concept for the vulnerability, illustrating how an unauthenticated attacker could transition from merely viewing a CloudWatch dashboard to listing EC2 instance tags within the target AWS account. The demonstration centered on the ability to bypass Cognito's session-scoping policy by forcing a "classic" authentication flow.

The practical steps involved were:

  1. Identifying a Target: The first step involved locating a publicly shared CloudWatch dashboard. Tsaousis successfully used basic Google dorks (e.g., inurl:dashboards.us-east-1.console.aws.amazon.com/dashboards/home?region=us-east-1&context=) to discover approximately 20 such URLs exposed on the internet. Additionally, he leveraged URL scanning services (like URLScan.io) to uncover another 10 or so, emphasizing that these dashboards were not difficult to find.
  2. Extracting Key Information: From the identified dashboard URL, the attacker would extract the context parameter. This base64-encoded JSON object contained two crucial pieces of information: the identityPoolId (labeled I) and the iamRoleArn (labeled O).
  3. Initiating the Classic Flow:
  • Using the extracted identityPoolId, the attacker would first make an API call to cognito-identity:GetId to obtain an IdentityId.
  • Crucially, instead of proceeding with the "enhanced" flow (which would apply a scope-down policy), the attacker would then use the IdentityId and the extracted iamRoleArn to make a direct API call to sts:AssumeRoleWithWebIdentity. This explicit role assumption is what bypasses Cognito's intended session policy.
  1. Obtaining Credentials: The sts:AssumeRoleWithWebIdentity call would return a set of temporary AWS credentials (Access Key ID, Secret Access Key, and Session Token) that possessed the full permissions of the iamRoleArn associated with the dashboard, without the intended scope-down.
  2. Executing Unauthorized Actions: With these credentials, the attacker could then load them into the AWS CLI and successfully execute commands like aws ec2 describe-tags. Tsaousis showed that this command, which previously failed with browser-obtained credentials, now worked, confirming the successful bypass and unauthorized access to EC2 tags.

Tsaousis highlighted real-world examples of publicly accessible dashboards he encountered during his hunting phase, such as:

  • EWN (Extreme Weather Notification): A platform for monitoring extreme weather conditions in Australia.
  • Monzie: A global scavenger hunt game where users scan QR codes around the world.

While he did not perform the full exploitation on these live systems for ethical reasons, their existence underscored the prevalence of the vulnerability. The speaker also touched upon the potential for escalating impact, such as invoking Lambda functions (lambda:InvokeFunction) if the dashboard's IAM role had been configured for custom widgets, which could lead to "denial of wallet" attacks. This was not directly demonstrated but explained as a logical extension of the initial access.

The PoC effectively showcased how a seemingly minor misconfiguration, combined with a "fail-open" default, could lead to a significant security breach, transforming an unauthenticated viewer into an actor with substantial, unintended permissions within an AWS account.

Defensive Implications

▶ Watch: Unauthorized operation: initial exploitation attempt fails (6:50)

The findings from Leo Tsaousis's research carry significant defensive implications for organizations leveraging AWS CloudWatch Dashboards and, more broadly, for anyone managing AWS permissions. Understanding this vulnerability is crucial for hardening cloud environments against similar logic flaws.

  1. Immediate Action: Unshare Public Dashboards: The most direct and immediate mitigation for this specific vulnerability is to unshare any CloudWatch Dashboards that are currently shared publicly. Tsaousis explicitly states that "you don't need to go and delete the dashboard altogether. You only need to unshare it." Unsharing a dashboard triggers the deletion of its associated Cognito Identity Pool, effectively revoking the exposed permissions and eliminating the attack vector. While AWS has patched the underlying bug, ensuring no new publicly shared dashboards suffer this flaw, existing ones created before the fix would still be vulnerable until unshared.
  1. Strict Least Privilege for Dashboard IAM Roles: This vulnerability underscores the critical importance of adhering to the principle of least privilege for all IAM roles, especially those automatically provisioned or suggested by AWS services.
  • Review Existing Roles: Organizations should audit the IAM roles associated with their CloudWatch Dashboards. Even if dashboards are not publicly shared, intended users (via Username/Password or SSO) can still obtain the full permissions of the IAM role.
  • Limit Permissions to Specific Resources: If features like "log table widgets" (requiring logs: permissions) or "custom widgets" (requiring lambda:InvokeFunction permissions) are used, ensure that the IAM policies are scoped down to the absolute minimum necessary resources (e.g., specific Lambda function ARNs, specific Log Group ARNs) rather than using broad wildcards (). This helps contain the blast radius if the role is compromised.
  1. Avoid Sensitive Data in EC2 Tags: Tsaousis highlighted that the initial exploit granted ec2:DescribeTags. While this might seem minor, it revealed a common anti-pattern: storing sensitive information in EC2 tags. Defenders must reinforce the AWS best practice that EC2 tags are not for sensitive data. This includes PII, contact details, plaintext credentials, or any proprietary information. Tags should be used purely for operational metadata, billing, and resource organization.
  1. Understand Cognito Identity Pool Configuration: For organizations that manually provision Cognito Identity Pools for their applications, it is paramount to understand the allowClassicFlow parameter. Always explicitly set allowClassicFlow to false in the CreateIdentityPool API call unless there's a well-understood and justified need for the classic flow, and the associated risks are thoroughly accepted and mitigated. The AWS console and Terraform now default this to false, but custom scripts or older SDK usages might still omit it.
  1. Beyond Scanner Results: The research originated from a scanner alert, but the true impact was only uncovered by digging deeper. Defenders should empower security teams to go beyond automated scanner findings, investigate the root cause of alerts, and understand the full potential attack surface and impact, even for seemingly low-severity issues.
  1. Security Monitoring Solutions Can Introduce Risk: The meta-takeaway is crucial: security monitoring tools, designed to enhance an organization's security posture, can inadvertently introduce new risks. Defenders should apply the same rigorous security scrutiny to their monitoring infrastructure as they do to their production applications. This includes reviewing configurations, access controls, and the underlying permissions granted to these tools.

By implementing these defensive strategies, organizations can significantly reduce their exposure to similar logic vulnerabilities and ensure that their monitoring solutions remain a security asset, not a liability.

Key Takeaways

  • Go Beyond Scanner Results: Automated security scanners are a starting point, but a deep understanding of cloud services and their interactions is necessary to uncover the true impact of findings, as demonstrated by the ec2:DescribeTags permission leading to a full role assumption.
  • Default Configurations Are Not Always Secure: The vulnerability stemmed from a "fail-open" default in Cognito's allowClassicFlow when left undefined by CloudWatch, highlighting that AWS service defaults are not inherently secure and require explicit configuration for hardening.
  • Remaining Risks for Intended Users: Even after AWS's patch for unauthenticated access, intended users (via Username/Password or SSO sharing) can still obtain the full, un-scoped-down permissions of the dashboard's IAM role, underscoring the need for continuous least-privilege enforcement.
  • Security Monitoring Solutions Can Introduce Risk: Ironically, a security monitoring solution (CloudWatch Dashboards) created a significant security risk, emphasizing the need to apply rigorous security assessments to all components of an infrastructure, including those designed for security.
  • Avoid Sensitive Data in EC2 Tags: This vulnerability served as a stark reminder of why sensitive information (PII, credentials, contact details) should never be stored in EC2 tags, as these can be unexpectedly exposed.
  • Review CloudWatch Dashboard IAM Permissions: Organizations should audit and apply the principle of least privilege to IAM roles backing CloudWatch Dashboards, especially when using features like custom widgets that require permissions like lambda:InvokeFunction.

About the Speaker(s)

Leo Tsaousis is a Senior Security Consultant at Reverse, a security consulting firm based in London, UK, which was formerly known as Secure Consulting. He leads the "attack path mapping" service at Reverse, focusing on comprehensive security exercises that often resemble purple team engagements. Tsaousis is an experienced technical researcher, a passion that has led him to speak at numerous security conferences. His expertise spans a wide range of cloud and infrastructure topics, including AWS, Active Directory, Kubernetes, and vulnerabilities in web and mobile applications. Throughout his career, he has been fortunate to discover and report vulnerabilities in products from various vendors, including IBM, Cisco, Wind Vision, Xiaomi, and, as detailed in this talk, AWS. He previously presented on Kubernetes at Cloud Village, demonstrating his consistent engagement with critical cloud security topics.

Reviews

Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT

Genuine original research with a clear chain of reasoning from scanner alert to unauthenticated role assumption — exactly the kind of cloud security work that deserves a stage slot. The finding is specific, the root cause is well-understood (fail-open default in allowClassicFlow), and the exploitation path is reproducible. Doesn't fully clear the 5-star bar because the blast radius is ultimately constrained: it requires a publicly shared dashboard and the worst-case impact is denial-of-wallet rather than account takeover.

Heather Calloway (CISO) — WEAK

Technically sound, well-documented AWS vulnerability research with a clear PoC and responsible disclosure. But it never climbs out of the advisory layer — there's no governance framing, no organizational accountability angle, and no meaningful guidance for the security leaders who set cloud policy and control IAM posture at scale.

→ Top-rated talks at Cloud Village @ DEF CON 33

All talks from Cloud Village @ DEF CON 33