> For the complete documentation index, see [llms.txt](https://0xb0b.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2026/incognito-travel.md).

# Incognito Travel

{% embed url="<https://www.hacksmarter.org/courses/10115bdd-ca15-49c4-b34c-670645fc55ab>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

## Scenario

Incognito Travel is rolling out a new authentication process for their flagship travel application. Before deploying to production, they have contracted Hack Smarter to rigorously test the new authentication flow. The target application leverages Amazon Cognito to handle its identity and access management.

## Summary

<details>

<summary>Summary</summary>

In Incognito Travel we begin with reconnaissance, identifying the target user Cory from the About page and confirming his existence through username enumeration at the login portal. We then enumerate the frontend source code and extract AWS Cognito configuration parameters, including the `userPoolId` and `clientId`. We create a new user account with credentials we control and retrieve the access token from browser local storage. Using this token with the AWS CLI, we query the Cognito identity provider to verify current user attributes. We then exploit Cognito's misconfiguration by updating our account's email address to a case-variant of the target user `Cory@hacksmarter.hsm`. Due to the application's improper reliance on email for user identification rather than the OpenID Connect `sub` claim, combined with Cognito's default allowance for authenticated users to modify their own email attributes, the case-insensitive email matching allows us to assume the victim's identity. Logging in with the modified credentials grants us authenticated access as the victim account

</details>

## Recon

We start the scenario and get the following website in scope.&#x20;

<figure><img src="/files/FIzi4g1Xl3Iq6p6Vl07X" alt=""><figcaption></figcaption></figure>

We do not perform a port scan and initially enumerate the page manually. When visiting the site, we have a travel portal infront of us with an about page and a login.

{% code overflow="wrap" expandable="true" %}

```
http://incognito-travel-frontend-cgid4d4epq9zfk.s3-website-us-east-1.amazonaws.com
```

{% endcode %}

<figure><img src="/files/dQum9vblgU9pOGLPjPBh" alt=""><figcaption></figcaption></figure>

From the `About` page, we can identify the user Cory with his email address `cory@hacksmarter.hsm`.

{% code overflow="wrap" expandable="true" %}

```
http://incognito-travel-frontend-cgid4d4epq9zfk.s3-website-us-east-1.amazonaws.com/#about
```

{% endcode %}

<figure><img src="/files/GE3PBjGZ2JRLLPppeB0F" alt=""><figcaption></figcaption></figure>

Next, we visit the login page, this is preset with another mail address `agent@hacksmarter.hsm`. We try this with arbitrary credentials and can see that this user does not exist by the resulting error message. Username enumeration is possible here.

{% code overflow="wrap" expandable="true" %}

```
http://incognito-travel-frontend-cgid4d4epq9zfk.s3-website-us-east-1.amazonaws.com/#about
```

{% endcode %}

<figure><img src="/files/EthZn8WMk2OaMoHxXn0e" alt=""><figcaption></figcaption></figure>

Next, we try the mail of Cory and this time we get an incorrect password message.

<figure><img src="/files/gT3oq8bPwPfYeqrfyQkL" alt=""><figcaption></figcaption></figure>

### Source Code Inspection

We take a closer look at the source code and find a `COGNITO_CONFIG` containing the `userPoolId`  and `clientId`.

<figure><img src="/files/akpPW9fGfULZGBn3ZfXa" alt=""><figcaption></figcaption></figure>

### Account Creation

But we also saw that we can request access at the login page. When we click the link, we're taken to a registration modal where we can create our own user account. We'll choose the following credentials:&#x20;

{% code overflow="wrap" expandable="true" %}

```
agent@hacksmarter.hsm:Pwnde123@! 
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
http://incognito-travel-frontend-cgid4d4epq9zfk.s3-website-us-east-1.amazonaws.com/#
```

{% endcode %}

<figure><img src="/files/c74uQp6TwIYDywlM9Y9U" alt=""><figcaption></figcaption></figure>

After registering the user we are able to log in. We have a dashboard in forn of us as a Guest user as it seems.

{% code overflow="wrap" expandable="true" %}

```
http://incognito-travel-frontend-cgid4d4epq9zfk.s3-website-us-east-1.amazonaws.com/#
```

{% endcode %}

<figure><img src="/files/O7mdTog5NLl25Ssypabl" alt=""><figcaption></figcaption></figure>

From the local storage tab in our developers tool we can retrieve the access token. Which would allow us to query user attributes... But more on that in the next section.

<figure><img src="/files/ggsFtkNtYHBdmZgwISzx" alt=""><figcaption></figcaption></figure>

### AWS Cognito

From the scenario and the source code, we can see that AWS Cognito is being used.

AWS Cognito is a service that handles user login, permissions, and user management for apps. It has two main parts: User Pools and Identity Pools.

User Pools let users create accounts and log in. Once logged in, users get an access token that lets them use AWS tools to view and change their account information.

## Access as <cory@hacksmarter.hsm>

However, AWS Cognito can also be misconfigured, as described in the following article, which could allow an account takeover if the app uses the email attribute to identify users. With that the app can be tricked into treating an attacker as someone else.&#x20;

> The vulnerability exists due to two key issues:
>
> 1. **Writable Attribute(s)**: By default, AWS Cognito allows authenticated users to modify their own attributes (including email) using the access token via the AWS API.<br>
> 2. **Improper User Identification**: Applications using the email attribute instead of the sub (subject) claim to identify users. According to the OpenID Connect specification, only the sub claim is guaranteed to be unique and should be used for user identification.

{% embed url="<https://www.cobalt.io/blog/full-account-takeover-via-aws-cognito-misconfiguration>" %}

We'll follow the blog and recreate the steps.

### **Get Cognito Access Token**

We're using the session with our newly created account. With the Dev Tools of our Browser of choice we inspect the Cookies, local storage, etc. to get the access token and do find it in the local storage.

<figure><img src="/files/bsZGvhyaOXUPXCNBTE2z" alt=""><figcaption></figcaption></figure>

### Verify Current User Attributes

First, we'll try to query the `cognito-idp` using the access token we received, and list the users attributes.

We save the `TOKEN` in a variable in our terminal to use it to query for the `cognito-idp` using AWS CLI.

{% code overflow="wrap" expandable="true" %}

```
export TOKEN=<TOKEN>
```

{% endcode %}

<figure><img src="/files/Q5B8JfvXFsrt6IvfyMzR" alt=""><figcaption></figcaption></figure>

Next, we retrieve the user's information from AWS Cognito.

{% code overflow="wrap" expandable="true" %}

```
aws cognito-idp get-user --region us-east-1 --access-token $TOKEN
```

{% endcode %}

<figure><img src="/files/NCGgHeFzRICfNIPxh7yx" alt=""><figcaption></figcaption></figure>

### **Update Email to Victim's Address (Case-Variant)**

With the `clientId` and your `access_token` we update the email attribute of the newly created account to `CORY@hacksmarter.hsm`.

{% code overflow="wrap" expandable="true" %}

```
aws cognito-idp update-user-attributes \
--region us-east-1 \
--access-token $TOKEN \
--user-attributes Name=email,Value=Cory@hacksmarter.hsm
```

{% endcode %}

<figure><img src="/files/eZsxF3HrgbyXaBg3E0Dm" alt=""><figcaption></figcaption></figure>

Next, we verify the change.

{% code overflow="wrap" expandable="true" %}

```
aws cognito-idp get-user --region us-east-1 --access-token $TOKEN
```

{% endcode %}

<figure><img src="/files/AQuy23r85kYGoNq4eA6L" alt=""><figcaption></figcaption></figure>

### Login as <cory@hacksmarter.hsm>

After we've configured the user's email of our newly created account, we'll try to log in agina as `cory@hacksmarter.hsm` using our credential pair:

{% code overflow="wrap" expandable="true" %}

```
Cory@hacksmarter.hsm:Pwnde123@!
```

{% endcode %}

<figure><img src="/files/QrQPFwNelizgN90HeBAs" alt=""><figcaption></figcaption></figure>

We succefully logged in and are authenticated as cory. We get access to the flag on the dashboard.&#x20;

<figure><img src="/files/p2ZImj3rWwwD5kbAtVZ7" alt=""><figcaption></figcaption></figure>
