LinkVortex writeup
LinkVortex is a Linux box that involves subdomain enumeration and source‑code disclosure via a .git directory. We will reuse hardcoded credentials, exploit a Ghost CMS arbitrary file read (CVE‑2023‑40028) to obtain SSH credentials, and escalate privileges through environment variable manipulation in a custom script.
Scan the target using nmap:
Nmap scan returns two ports: 22 and 80.
Add linkvortex.htb to the /etc/hosts file.
Fuzz vhosts using ffuf:
This finds dev.linkvortex subdomain.
Further directory brute‑force returns a .git directory on that subdomain.
Extract .git contents using git‑dumper or another tool:
View staged but not committed changes:
View what has changed in the authentication.test.js file:
And we have found hardcoded credentials:
test@example.com:OctopiFociPilfer45
And from nmap we know that there is a /ghost endpoint. If you load it, it contains an admin panel.

Check for credentials reuse by using the admin email instead of test@example.com.

And it works!
This instance’s version is outdated.

It has a public exploit available:
https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028
Then you can review Ghost’s source code to understand what file we need to target to get credentials. In this case we need:
/var/lib/ghost/config.production.json
We get the following credentials:
bob@linkvortex.htb:fibber-talented-worth
Those credentials work on SSH:
Turns out bob can run this script as root without credentials.
Script contents:
#!/bin/bash
CHECK_CONTENT=false
# ... rest of script
In CHECK_CONTENT=false, false looks like a boolean but it’s actually the /usr/bin/false binary. We can change CHECK_CONTENT to sudo to get root:
There are two alternative ways to exploit this script:
Double symlink: You can create a symlink that points to another symlink. Then
/usr/bin/readlinkwill resolve only to the second symlink without following it further. Then you can setCHECK_CONTENT=true, and the script will attempt to read the second symlink, which could be pointed at/root/.ssh/id_rsaor/root/root.txt(the flag).Race condition: You could exploit a race condition between the moment the file is moved to quarantine and when it is read.
if ; then <-This loop should be set up in the quarantine directory (
/var/quarantined):while ; do ; doneThen by running:
CHECK_CONTENT=trueA legitimate file would be moved to quarantine, where it would then be immediately replaced with a symlink pointing to
/root/.ssh/id_rsa.
Credentials
test@example.com:OctopiFociPilfer45
admin@linkvortex.htb:OctopiFociPilfer45
bob@linkvortex.htb:fibber-talented-worth