In this short blog post, we describe how to retrieve AWS security credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN) when authenticated in the AWS Console.

Introduction

I have access to the AWS console; how do I retrieve the AWS security credentials corresponding to my role?” is a question I’ve asked myself more than once, typically when using identity federation, and assuming a role in an AWS account using an IdP that doesn’t support the CLI. It’s also very relevant in pentesting or red teaming, where you might have stolen a victim’s browser cookies and would like to leverage their access from the CLI.

The AWS console doesn’t directly make use of the usual AWS security credentials. Instead of sending API requests to the AWS services API endpoints, it proxies it through an AWS console backend service, and requests are authenticated with an AWS console-specific cookie.

POST /ec2/ecb/elastic/?call=com.amazonaws.ec2.AmazonEC2.DescribeInstances
Host: eu-west-1.console.aws.amazon.com
Cookie: aws-creds-code-verifier=..; JSESSIONID=..; aws-creds=..
POST /
Host: ec2.eu-west-1.amazonaws.com

Action=DescribeInstances&Version=2016-11-15

Where the aws-creds cookie is an encoded JSON object containing encrypted data.

AWS CloudShell

AWS CloudShell, released in late 2020, is a web-based shell in the AWS console allowing to run CLI commands directly from the web interface:

The environment doesn’t contain AWS security credentials. Running the AWS CLI in debug mode, we can see it’s using the AWS Instance Metadata Service to retrieve security credentials:

$ aws ec2 describe-regions --debug
...
DEBUG - Credentials need to be refreshed.
DEBUG - http://localhost:1338 "GET /latest/meta-data/container/security-credentials HTTP/1.1" 200 1496
DEBUG - Retrieved credentials will expire at: 2021-06-05 16:59:59+00:00

The Undocumented Endpoint

This tells us that CloudShell uses an undocumented IMDS-like endpoint to retrieve the security credentials needed to perform API calls. I say “IMDS-like” since it listens on localhost instead of the usual 169.254.169.254 and doesn’t seem to expose any other endpoint.

Therefore, we can call it as well and retrieve our AWS security credentials!

$ TOKEN=$(curl -XPUT localhost:1338/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 60")
$ curl localhost:1338/latest/meta-data/container/security-credentials -H "X-aws-ec2-metadata-token: $TOKEN"
{
        "LastUpdated": "1970-01-01T00:00:00Z",
        "Type": "",
        "AccessKeyId": "ASIAYYF...",
        "SecretAccessKey": "UJbW..5k",
        "Token": "IQo..MA==",
        "Expiration": "2021-06-05T17:06:59Z",
        "Code": "Success"
}

Et voilà! Thanks a lot to Rich Mogull @ DisruptOps for the idea of looking in CloudShell.

Let’s continue the discussion on Twitter!

  • Do you know another way to retrieve AWS security credentials from the AWS console?
  • What’s your main use-case for it?
  • Have you experimented with the CloudShell undocumented IMDS-like service?

Post Views: 35