Nmap

# Nmap 7.95 scan initiated Sun Feb  2 17:15:29 2025 as: /usr/lib/nmap/nmap -p22,80 -sCV -oN nmap/scripts.txt 10.10.11.47
Nmap scan report for 10.10.11.47
Host is up (0.060s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:f8:b9:68:c8:eb:57:0f:cb:0b:47:b9:86:50:83:eb (ECDSA)
|_  256 a2:ea:6e:e1:b6:d7:e7:c5:86:69:ce:ba:05:9e:38:13 (ED25519)
80/tcp open  http    Apache httpd
|_http-server-header: Apache
|_http-title: Did not follow redirect to http://linkvortex.htb/
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 at Sun Feb  2 17:15:38 2025 -- 1 IP address (1 host up) scanned in 8.42 seconds

The Nmap scan reveals that only two ports are open, SSH and HTTP. I decided to ignore port 22 since I don’t have any credentials.

Additionally, Nmap discovered the hostname linkvortex.htb, which I added to my /etc/hosts file.

add hostname to /etc/hosts

Http: Linkvortex.htb

Navigating to http://linkvortex.htb, I found that the website is a blog about computer hardware. Scrolling to the footer, I noticed the text Powered by Ghost, indicating that the site uses the Ghost CMS.

website page

website footer

Performing light enumeration, I reviewed all blog posts and discovered that they were created by a single user, which is admin.

user named admin

Additionally, by inspecting the page source, I found the Ghost CMS version, which is 5.58.

view page source

I also attempted directory fuzzing on the website, which revealed multiple Ghost-related directories. However, the results were overwhelming and difficult to analyze. I also found the Ghost API, but authentication was required to interact with it.

Http: Dev.linkvortex.htb

Since I hadn’t found anything useful so far, I decided to perform virtual host enumeration using ffuf. Surprisingly, I discovered a new subdomain, dev.linkvortex.htb. I added this to my /etc/hosts file.

ffuf found dev vhost

add dev to /etc/hosts

git-dumper

Upon visiting http://dev.linkvortex.htb, I found a simple “Launching Soon” page. I performed directory fuzzing and discovered that the .git directory was exposed.

website with launching soon page

I downloaded the entire .git directory using git-dumper. Then, I opened it in VSCode to analyze its Git history. I found an interesting file, authentication.test.js, marked with M, indicating it had been Modified. Checking the changes, I found a password.

modified file

Ghost: Authenticated Arbitrary File Read

I previously identified the Ghost CMS version (5.58) but forgot to mention that I also searched for known vulnerabilities. I found a PoC exploit for CVE-2023-40028, which allows authenticated arbitrary file read.

In summary, this vulnerability allows authenticated users to upload symlinked files, enabling them to read arbitrary files on the system.

Ghost is an open source content management system. Versions prior to 5.59.1 are subject to a vulnerability which allows authenticated users to upload files that are symlinks. This can be exploited to perform an arbitrary file read of any file on the host operating system. Site administrators can check for exploitation of this issue by looking for unknown symlinks within Ghost’s content/ folder. Version 5.59.1 contains a fix for this issue. All users are advised to upgrade. There are no known workarounds for this vulnerability.

To exploit this, I needed valid credentials. Since I had found a password earlier, I assumed the username format was [email protected] and ran the PoC. It worked!

poc read /etc/passwd

Next, I searched for the location of the Ghost CMS configuration file. Many sources pointed to /var/www/ghost, but I was unable to access it. Checking the .git directory again, I found a Dockerfile.ghost, which revealed that the configuration file is located at /var/lib/ghost/config.production.json.

location ghost config file

Using the PoC, I successfully retrieved the Ghost config file, which contained another set of credentials belonging to bob.

poc read ghost config

User: Bob

I attempted to use Bob’s credentials to log in via SSH, and it worked! I now had access to the machine as bob. The first thing I checked was sudo permissions using sudo -l. I found that bob could run a script called clean_symlink.sh with sudo privileges.

ssh as bob

Then I read the clean_symlink.sh file and found that it is a simple Bash script that checks if the provided argument ends with .png and verifies whether it is a symbolic link. If it is, the script moves it to quarantine.

Additionally, if CHECK_CONTENT is set to true, the script will read and display the file’s content. It also filters out links that contain either etc or root in their paths.

#!/bin/bash

QUAR_DIR="/var/quarantined"

if [ -z $CHECK_CONTENT ];then
  CHECK_CONTENT=false
fi

LINK=$1

if ! [[ "$LINK" =~ \.png$ ); then
  /usr/bin/echo "! First argument must be a png file !"
  exit 2
fi

if /usr/bin/sudo /usr/bin/test -L $LINK;then
  LINK_NAME=$(/usr/bin/basename $LINK)
  LINK_TARGET=$(/usr/bin/readlink $LINK)
  if /usr/bin/echo "$LINK_TARGET" | /usr/bin/grep -Eq '(etc|root)';then
    /usr/bin/echo "! Trying to read critical files, removing link [ $LINK ] !"
    /usr/bin/unlink $LINK
  else
    /usr/bin/echo "Link found [ $LINK ] , moving it to quarantine"
    /usr/bin/mv $LINK $QUAR_DIR/
    if $CHECK_CONTENT;then
      /usr/bin/echo "Content:"
      /usr/bin/cat $QUAR_DIR/$LINK_NAME 2>/dev/null
    fi
  fi
fi

Since the script filtered out symlinks pointing to etc or root, I bypassed the restriction using a chained symlink technique.

symlink chained

Finally, I read the root user’s SSH key using the same technique. I then used the key to SSH into the machine as root.

ssh as root